李迎辉

李迎辉的博客

他的个人主页  他的博客

Uliweb之Cache

李迎辉  2009年11月04日 星期三 12:23 | 1746次浏览 | 3条评论

在经过对beaker中的session替换之后,我终于又把cache给替换掉了。完全是自个儿重写。一方面它可以象一个dict一样工作,同时可以通过put, get来调用。使用这两个函数的好处就是可以有更多的参数。目前这个类在uliweb/lib/weto/cache.py中。

创建cache

import weto.cache

cache = weto.cache.Cache()

这样可以创建一个cache。因为没有指定Cache类的初始化参数,因此会自动以file格式创建cache。如果需要指定其它的格式和参数,可以设置:

storage_type, options, expiry_time

这三个参数。storage是类型,目前只支持'file', 'dbm', 'database',分别对应三种不同的存储类型。

options则根据不同的类型有所区别,比如'file'类型需要传入'data_dir',用以指定cache保存的路径。而'database'则需要指明要使用的表名和数据库连接的一些信息。

expiry_time是指定缺省的超时时间。这是当你在put时没有指定超时时间时使用的,在调用put时可以单独设定。

cache.get(key)

这样的调用,如果key不存在,或超时则会引发一个异常抛出CacheKeyException异常。

如果不想引发异常,则可以:

cache.get(key, default)

其中default不能为None,这样当key不存在,则不会引发异常,返回default值。如果为None,则同get(key)的效果。

cache.put(key, value, expire=None)

这样可以设置一个cache。如果expire没有传入则使用缺省的超时时间。时间以秒为单位。

同时为了方便函数的封装,还提供了

cache.cache(key=None, expire=None)

这个decorator。例如:

@cache.cache(expire=15)
def f(*args, **kwargs):

@cache.cache(key, expire=15)
def f(*args, **kwargs):

这两种都是可以的,区别在于前一个没有key参数,那它将根据函数名和参数来生成一个key,而后面则是由用户主动指定了一个key。

在进行上进的改造之后,原来的beaker就删除了,这样uliweb中不再使用beaker了。同时对原uliweb.contrib.cache进行了修改,去掉了middle_cache.py,而采用让用户自行调用的机制。同时为了同app的配置功能相结合和方便用户使用,在uliweb/utils/cache.py中编写了一个get_cache()的函数,同时对Cache类的增加了page方法。

get_cache()可以自动从settings中找到相应的配置。目前主通过两个secion来控制的:

[CACHE]和[CACHE_STORAGE],前者用来控制cache的类型和超时时间。后者是用来针对每一种类型来设置与存储相关的配置信息。在调用get_cache()时,你还可以传入一些参数,它的原型是:

def get_cache(cache_setting_name='CACHE', cache_storage_setting_name='CACHE_STORAGE'):

即可以指明使用其它的配置名,这样就可以在你的settings.ini中存放不同的cache的配置,通过get_cache来使用不同的cache机制。

为什么要对Cache进行扩展,Cache.cache原来是针对函数本身和它的参数,但是这样对于view有一点问题。有些view可能通过QUERY_STRING来处理不同的传入参数,因此在url上它们不同,但是在view函数上是完全一样,因此这种只根据函数本身和参数是有问题的。因此扩展的page这个decorator使用了request.url值,它是一个完整的访问路径,包括了QUERY_STRING信息。因此为了生成静态cache,可以使用改造后的Cache类。当你调用get_cache()时返回的cache对象已经是使用了这个新的Cache类了。

所以为了方便和更适合在Uliweb环境下使用,可以使用uliweb.utils.cache的get_cache()函数。例如:

from uliweb.utils.cache import get_cache()
cache = get_cache() #使用缺省的settings.ini设置。因此需要加入uliweb.contrib.cache这个app
@cache.cache(expire=15)
@expose('/index')
def index():
    return {}

现在我把uliwebproject也添加了cache的支持,不过发现的问题是,不能简单的使用@cache.page()来对view方法进行处理。原因是:

在view方法中有对cookie的处理,采用cache的方式会屏蔽掉这块处理

因此在uliwebproject中并不是使用的decorator的方式,而是在view中对可以cache化的部分进行了手工处理,如:

        cache = get_cache()

        @cache.cache(_f)

        def f():

            content = file(_f).read()

            if render:

                content = to_html(template(content, env=application.get_view_env()))

            else:

                content = to_html(content)

            return application.template('show_document.html', locals())

 

        response.write(f())

        return response

完全是手工来处理了。

评论

我的评论:

发表评论

请 登录 后发表评论。还没有在Zeuux哲思注册吗?现在 注册 !
邢兴

回复 邢兴  2009年11月10日 星期二 09:50

如果不用参数传递的方式呢?

用不同的 cache saver 来实现实际的存储,然后用 saver.install() 安装不同的 saver 来实现不同的调用。
这样,在切换不同的 cache 的时候,不需要总是去改参数。

根据接口,用户也可以实现自己的 saver,然后 install 到 cache 系统里。这样扩展性更好一些~~

1条回复

  • 李迎辉

    回复 李迎辉  2009年11月10日 星期二 11:29

    get_cache()就是为了获取一个实际的cache对象。和install差不多。因为在创建cache saver时一定也有不同的参数传入。只是不同的扩展方法而已。

    0条回复

雷振林

回复 雷振林  2009年11月04日 星期三 19:28

辛苦了!

0条回复

暂时没有评论

Zeuux © 2024

京ICP备05028076号