我正在尝试使用Beaker的缓存库,但我无法使其正常工作。
这是我的测试代码。
class IndexHandler():
@cache.cache('search_func', expire=300)
def get_results(self, query):
results = get_results(query)
return results
def get(self, query):
results = self.get_results(query)
return render_index(results=results)我尝试过Beaker文档中的示例,但我看到的是
<type 'exceptions.TypeError'> at /
can't pickle generator objects很明显,我遗漏了一些东西,但我找不到解决方案。
顺便说一句,如果缓存类型设置为"file“,则会发生此问题。
发布于 2011-01-03 01:04:34
如果您将beaker配置为保存到文件系统,那么您可以很容易地看到每个参数也被酸洗了。示例:
tp3
sS'tags <myapp.controllers.tags.TagsController object at 0x103363c10> <MySQLdb.cursors.Cursor object at 0x103363dd0> apple'
p4注意,缓存"key“不仅包含我的关键字"apple”,还包含特定于实例的信息。这是相当糟糕的,因为特别是“self”在不同的调用中不会是相同的。缓存每次都会导致未命中(并且会被无用的键填满)。
带有缓存注释的方法应该只有才有对应于您脑海中的任何“键”的参数。为了解释这一点,假设你想存储"John“对应于值555-1212的事实,并且你想对其进行缓存。除了字符串作为参数外,您的函数不应接受任何参数。你传入的任何参数都应该在调用之间保持不变,所以像"self“这样的东西是不好的。
实现这一点的一种简单方法是内联函数,这样您就不需要传递键以外的任何东西。例如:
def index(self):
# some code here
# suppose 'place' is a string that you're using as a key. maybe
# you're caching a description for cities and 'place' would be "New York"
# in one instance
@cache_region('long_term', 'place_desc')
def getDescriptionForPlace(place):
# perform expensive operation here
description = ...
return description
# this will either fetch the data or just load it from the cache
description = getDescriptionForPlace(place)您的缓存文件应该类似于以下内容。请注意,只有'place_desc‘和'John’被保存为键。
tp3
sS'place_desc John'
p4发布于 2010-07-04 00:05:31
我看到beaker文档没有明确提到这一点,但是,很明显,装饰函数必须拾取调用它的参数(作为键的一部分放到缓存中,检查条目是否存在,否则以后再添加它) --而且,生成器对象是不可拾取的,正如错误消息告诉您的那样。当然,这意味着query是一个生成器对象。
为了使用烧杯或任何其他类型缓存,您应该传递(而不是query生成器对象)可用于构建查询的(可拾取的) parameters --字符串、数字、字典、列表、元组等,其组合方式对您来说很容易,而且只在get_results的函数体中“及时”地构建查询。这样,参数将是可拾取的,并且缓存将会工作。
如果方便,您可以构建一个简单pickleable类,该类的实例“代表”查询,模拟所需的任何初始化和参数设置,并仅在调用需要实际查询对象的方法时执行即时实例化。但这只是一个“方便”的想法,并不会改变上一段中解释的基本概念。
发布于 2010-07-11 00:47:55
尝试使用return list(results)而不是return results,看看是否有帮助。
烧杯文件缓存需要能够拾取缓存键和值;大多数迭代器和生成器都是不可拾取的。
https://stackoverflow.com/questions/3170882
复制相似问题