首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >添加到memcache时的PicklingError

添加到memcache时的PicklingError
EN

Stack Overflow用户
提问于 2012-11-23 21:22:21
回答 1查看 486关注 0票数 2

我第一次尝试在App Engine上使用memcache,结果遇到了一个"PicklingError“。

我第一次尝试memcache的地方是在网站的主页上,在那里我从数据存储中抓取内容:

代码语言:javascript
复制
def get(self):
    content = memcache.get('home:content')
    if content is None:
        all_content = Content.all()
        all_content.order("-views")
        all_content.filter('published =', True)
        content = all_content.run(batch_size=5, limit=5)
        memcache.add(key='home:content', value=content, time=120)

(请注意,即使我没有尝试将内容查询对象放入memcache中,也可以很好地工作。下面是它在最后一行命中的错误(memcache.add...):

代码语言:javascript
复制
PicklingError: Pickling of datastore_query.Batcher is unsupported.

以下是内容的模型:

代码语言:javascript
复制
class Content(db.Model):
    category = db.StringProperty(required = True)
    content_type = db.StringProperty(required = True)
    published = db.BooleanProperty(default = False)
    title = db.StringProperty(required = True)
    abstract = db.TextProperty(required = True)
    summary = db.TextProperty(required = True)
    URL = db.LinkProperty(required = True)
    youtube_id = db.StringProperty(required = False)
    thumbnail = db.LinkProperty(required = True)
    post_author = db.StringProperty(required = True)
    author_url = db.LinkProperty(required = False)
    date_post = db.DateTimeProperty(required = True, auto_now_add = True)
    date_source = db.DateTimeProperty(required = False)    
    # todo: split out to use decent shardedcounter approach
    views = db.IntegerProperty(default = 0)
    up_votes = db.IntegerProperty(default = 0)
    down_votes = db.IntegerProperty(default = 0)    
    def votes(self):
        return self.up_votes - self.down_votes

我正在努力弄清楚什么是PicklingError,以及它与试图将Query对象存储到memcache中有何关系。我的问题是:我做错了什么?这是因为我正在尝试缓存迭代器吗?缓存Query对象并需要在每次页面加载时调用.run()有什么价值吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-11-24 02:50:08

看看memcachesource

简而言之,这是因为您的值必须以一种简单的方式序列化,所以默认情况下使用pickle (实际上是cPickle)来序列化您传入的对象。

当调用add时,将调用_set_with_policy,后者随后将调用_set_multi_async_with_policy。在_set_multi_async_with_policy中,键-值对作为mapping传入,并且是serialized in a loop

代码语言:javascript
复制
for key, value in mapping.iteritems():
  server_key = _key_string(key, key_prefix, user_key)
  stored_value, flags = _validate_encode_value(value, self._do_pickle)

在帮助器方法_validate_encode_value中,如果传入的对象是不可识别的对象,如intboolstr,则方法attempts to pickle该对象:

代码语言:javascript
复制
else:
  stored_value = do_pickle(value)
  flags |= TYPE_PICKLED

更新:当您调用run时,您将获得一个iterator object,其中包含查询中包含的某些对象。如果你只想要过滤结果,你可以把这个迭代器通过

代码语言:javascript
复制
content = list(all_content.run(batch_size=5, limit=5))

如果你想保留其他的部分,你需要一些定制的pickler。在Batcher中作为you can see

代码语言:javascript
复制
  def __getstate__(self):
    raise pickle.PicklingError(
        'Pickling of datastore_query.Batch is unsupported.')

datastore_query中定义的大多数类--也就是定义大多数查询行为的类--强烈反对在调用__getstate__时抛出PicklingError。如果您从来没有使用过它,那么__getstate____setstate__是一些自定义方法,它们可以帮助您对对象进行pickle和unpickle操作。

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

https://stackoverflow.com/questions/13530018

复制
相关文章

相似问题

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