无法让Beaker缓存工作

时间:2010-07-03 08:43:14

标签: python beaker

我正在尝试使用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”,则会出现此问题。

3 个答案:

答案 0 :(得分:3)

如果将beaker配置为保存到文件系统,则可以很容易地看到每个参数也被腌制。例如:

tp3
sS'tags <myapp.controllers.tags.TagsController object at 0x103363c10> <MySQLdb.cursors.Cursor object at 0x103363dd0> apple'
p4

请注意,缓存“key”不仅包含我的关键字“apple”,还包含特定于实例的信息。这非常糟糕,因为特别是“自我”在调用中不会相同。缓存每次都会导致错过(并且会填满无用的密钥。)

使用缓存注释的方法应该具有与您想到的任何“密钥”对应的参数。换句话说,假设您想要存储“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

答案 1 :(得分:1)

我看到beaker文档没有明确提到这一点,但是,显然,decorate函数必须挑选它所调用的参数(用作密钥的一部分进入缓存,以检查条目存在,并在以后添加它) - 并且,生成器对象不是pickleable,因为错误消息告诉你。这意味着query当然是一个生成器对象。

为了使用烧杯或任何其他类型的缓存,您应该做的是传递({pickleable)query而不是parameters生成器对象,该查询可以是内置 - 字符串,数字,dicts,列表,元组等等,以任何方式组成,易于安排,并且只在{{1}的函数体内“及时”构建查询}}。这样,参数将是可选择的,缓存将起作用。

如果方便,您可以构建一个简单的pickleable类,其实例“代表”查询,模拟您需要的任何初始化和参数设置,并仅在需要实际查询对象的某些方法时执行实时实例化调用。但这只是一个“方便”的想法,并没有像前一段所解释的那样改变基本概念。

答案 2 :(得分:1)

尝试使用return list(results)代替return results,看看是否有帮助。

beaker文件缓存需要能够腌制缓存键和值;大多数迭代器和生成器都是不可用的。