首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法使Beaker缓存正常工作

无法使Beaker缓存正常工作
EN

Stack Overflow用户
提问于 2010-07-03 16:43:14
回答 3查看 1.2K关注 0票数 1

我正在尝试使用Beaker的缓存库,但我无法使其正常工作。

这是我的测试代码。

代码语言:javascript
复制
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文档中的示例,但我看到的是

代码语言:javascript
复制
<type 'exceptions.TypeError'> at /
can't pickle generator objects

很明显,我遗漏了一些东西,但我找不到解决方案。

顺便说一句,如果缓存类型设置为"file“,则会发生此问题。

EN

回答 3

Stack Overflow用户

发布于 2011-01-03 01:04:34

如果您将beaker配置为保存到文件系统,那么您可以很容易地看到每个参数也被酸洗了。示例:

代码语言:javascript
复制
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“这样的东西是不好的。

实现这一点的一种简单方法是内联函数,这样您就不需要传递键以外的任何东西。例如:

代码语言:javascript
复制
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’被保存为键。

代码语言:javascript
复制
tp3 
sS'place_desc John' 
p4
票数 3
EN

Stack Overflow用户

发布于 2010-07-04 00:05:31

我看到beaker文档没有明确提到这一点,但是,很明显,装饰函数必须拾取调用它的参数(作为键的一部分放到缓存中,检查条目是否存在,否则以后再添加它) --而且,生成器对象是不可拾取的,正如错误消息告诉您的那样。当然,这意味着query是一个生成器对象。

为了使用烧杯或任何其他类型缓存,您应该传递(而不是query生成器对象)可用于构建查询的(可拾取的) parameters --字符串、数字、字典、列表、元组等,其组合方式对您来说很容易,而且只在get_results的函数体中“及时”地构建查询。这样,参数将是可拾取的,并且缓存将会工作。

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

票数 1
EN

Stack Overflow用户

发布于 2010-07-11 00:47:55

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

烧杯文件缓存需要能够拾取缓存键和值;大多数迭代器和生成器都是不可拾取的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3170882

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档