python 缓存机制

今天在看《 python高级编程》 python缓存这一小节。在这里记录下学习笔记。

什么是缓存大家都明白,就是对某一个复杂的计算进行缓存,等待下一次请求的时候可以避免再次计算而直接返回结果。这样可以改善程序的性能 。

一、最基础的缓存

看《python高级编程》 中的程序例子:


#!/usr/bin/python  
# -*-  coding:utf8  -*-

import time
import hashlib
import pickle

from itertools import chain
cache = {}

def is_obsolete(cache_entry,duration):
    ''' 检查cache有没有过期  '''
    return time.time() - cache_entry['time'] > duration


def compute_key(function,args,kw):
    ''' 对函数进行 hash 取得唯一值'''
    key = pickle.dumps((function.func_name,args,kw))
    return hashlib.sha1(key).hexdigest()

def memoize(duration=10):
    def _memoize(function):
        def __memoize(*args,**kw):
            key = compute_key(function,args,kw)

            if ( key in cache and
                not is_obsolete(cache[key],duration)):
                print 'we got a winner'
                return cache[key]['value']

            result = function(*args,**kw)

            cache[key] = {'value':result,
                          'time':time.time()}
            return result

        return __memoize

    return _memoize

@memoize(10) #10秒之后缓存会失效 
def very_very_complex_stuff(a,b):
    print a+b

very_very_complex_stuff(100,200)


以上的代码,可以称之为 缓存装饰器 , 使用起来也是较为方便 。


二、实际如何应用 

一个技术 有没有价值,最看它可以运用在什么地方 。千言万语,还不如我们一起来看下Django 的源码吧,看django是如何使用缓存的.

有使用Django的朋友,可以参考文章:Django缓存机制 http://py3k.cn/chapter13/

其中有一个View层的缓存,代码示例如下:

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)
def my_view(request, param):
    # ...
看到这里,大概明白了 缓存装饰器 可以应用在哪些地方 。接下来我们看下Django 的实现方法 :


Django的 FetchFromCacheMiddleware 中间件会处理这个请求:


class FetchFromCacheMiddleware(object):
    
    def __init__(self):
        ………………………………

    def process_request(self, request):
        """
        Checks whether the page is already cached and returns the cached
        version if available.
        """
        if not request.method in ('GET', 'HEAD'):
            request._cache_update_cache = False
            return None # Don't bother checking the cache.


由于django 封装了 基于内存的缓存、基于文件的缓存 、基于memcache的缓存等接口。 这里主要看基于文件的缓存 。


ubuntu@yee:/usr/local/lib/python2.7/dist-packages/django/core/cache/backends$ vim filebased.py
def set(self, key, value, timeout=None, version=None)://value 是一个response对象 
        key = self.make_key(key, version=version) #创建key 
        self.validate_key(key)  #验证key 是否已经存在

        fname = self._key_to_file(key)
        dirname = os.path.dirname(fname)

        if timeout is None:
            timeout = self.default_timeout

        self._cull()

        try:
            if not os.path.exists(dirname):
                os.makedirs(dirname)

            f = open(fname, 'wb')
            try:
                now = time.time()
                pickle.dump(now + timeout, f, pickle.HIGHEST_PROTOCOL)
                pickle.dump(value, f, pickle.HIGHEST_PROTOCOL) #将value 写入 文件中缓存起来
            finally:
                f.close()
        except (IOError, OSError):
            pass


Django的方法是,将response对象 pickle 之后保存在文件中。跟<python高级编程>中的方法是一样的。

获取缓存 :

def get(self, key, default=None, version=None):
        key = self.make_key(key, version=version)
        self.validate_key(key)

        fname = self._key_to_file(key)
        try:
            f = open(fname, 'rb')
            try:
                exp = pickle.load(f)
                now = time.time()
                if exp < now:
                    self._delete(fname)
                else:
                    return pickle.load(f)
            finally:
                f.close()
        except (IOError, OSError, EOFError, pickle.PickleError):
            pass
        return default

通过django 可以看出python的缓存是如何实现的了。如果想更深入的了解,还需要更多的去研究源码。

笔记就记到这里。Over。























你可能感兴趣的:(python,缓存)