我正试图在App Engine上第一次使用memcache并且遇到了“PicklingError”。
我尝试过memcache的第一个地方是在网站的主页上,我从数据存储中获取内容:
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)
(请注意,如果没有尝试将内容Query对象放入memcache,这样可以正常工作。这是它在最后一行(memcache.add ...)上发生的错误:
PicklingError: Pickling of datastore_query.Batcher is unsupported.
以下是内容的模型:
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()?
答案 0 :(得分:2)
查看memcache
的{{3}}。
简而言之,这是因为您的值必须以简单的方式序列化,因此默认情况下pickle
(实际上cPickle
)用于序列化您传入的对象。
调用add
时,会调用_set_with_policy
,然后调用_set_multi_async_with_policy
。在_set_multi_async_with_policy
中,键值对传递为mapping
并且为source:
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
中,如果传入的对象不是可识别的对象,例如int
,bool
,str
,方法serialized in a loop对象:
else:
stored_value = do_pickle(value)
flags |= TYPE_PICKLED
更新:当您调用run时,会返回attempts to pickle,其中包含查询中包含的某些对象。如果您只想挑选结果,可以通过
将此迭代器强制转换为列表content = list(all_content.run(batch_size=5, limit=5))
如果您想要保留其他部分,您需要某种自定义选择器。作为Batcher
中的iterator object:
def __getstate__(self):
raise pickle.PicklingError(
'Pickling of datastore_query.Batch is unsupported.')
datastore_query
中定义的大多数类 - 定义大多数查询行为的相同类 - 强烈反对在调用PicklingError
时抛出__getstate__
来进行酸洗。如果您从未玩过它,__getstate__
和__setstate__
是自定义方法,可以帮助挑选和取消对象。