社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

python缓存实现一例与Django缓存小析

爱情的枪 • 11 年前 • 5551 次点击  

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

一、最基础的缓存

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

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的缓存等接口。 这里主要看基于文件的缓存 。

写缓存:

/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的缓存是如何实现的了。如果想更深入的了解,还需要更多的去研究源码。

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/324
 
5551 次点击  
文章 [ 1 ]  |  最新文章 11 年前