PicklingError:不能pickle <class ... =“”>:它与GAE </class>中的对象不同

时间:2012-01-23 02:38:57

标签: python google-app-engine pickle

我在GAE Python应用程序中从这行代码中得到了一个PicklingError:

deferred.defer(email_voters_begin, ekey, voter_list)

这三个论点是:

  • email_voters_begin - Python函数,例如,函数email_voters_begin位于0x1035d4488
  • ekey - 我定义的实体的关键,例如,打印为agdvcGF2b3Rlcg4LEghFbGVjdGlvbhgCDA
  • voter_list - 我定义的对象列表,例如,[models.Voter object at 0x103d3d310,...]

当此行作为我的测试的一部分执行时(使用webtest和nosegae),我收到以下错误:

Traceback (most recent call last):
  [...]
  File "/Users/joneill/OpenSTV/OpenSTV/trunk/OpaVote-HR/tasks.py", line 29, in init_voters_and_send_email
    deferred.defer(email_voters_begin, ekey, voter_list)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/deferred/deferred.py", line 249, in defer
    pickled = serialize(obj, *args, **kwargs)
  File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/deferred/deferred.py", line 221, in serialize
    return pickle.dumps(curried, protocol=pickle.HIGHEST_PROTOCOL)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1374, in dumps
    Pickler(file, protocol).dump(obj)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump
    self.save(obj)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  [...]
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 396, in save_reduce
    save(cls)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 753, in save_global
    (obj, module, name))
PicklingError: Can't pickle <class 'google.appengine.ext.blobstore.blobstore.BlobInfo'>: it's not the same object as google.appengine.ext.blobstore.blobstore.BlobInfo

请注意,Voter中传递的deferred.defer()个实体没有BlobReference属性,但Voter个实体的ReferenceProperty实体确实有BlobReference个实体确实有{{1}}属性。我不认为任何BlobInfo对象都会成为pickle的一部分,但错误表明其中包含了一个。

当我使用开发服务器从浏览器窗口运行相同的代码时,不会发生此错误。

我很难过如何调试这个问题,我们将非常感谢任何想法。

2 个答案:

答案 0 :(得分:1)

您永远不应该将模型实例传递给延迟。改为使用键:

deferred.defer(email_voters_begin, ekey, [v.key() for v in voter_list])

在您的email_voters_begin中:

def email_voters_begin(ekey, voters_keys):
    voter_list = models.Voter.get(voters_keys)

答案 1 :(得分:1)

可能会发生这种情况,因为您已在至少一个Voter对象上检索到ReferenceProperty。取消引用ReferenceProperty后,模型实例会对其进行缓存。酸洗也会腌制任何缓存的对象,因此它会尝试序列化Voter实例,引用的实例及其BlobInfo

一般来说,正如Skirmantas指出的那样,将模型实例传递给延迟通常是个坏主意。在可能的情况下,发送密钥,如果不是,则将实例序列化为协议缓冲区并发送它们。