PicklingError:无法 pickle:它与 GAE 中的 ... 不是同一对象

发布于 2024-12-28 20:50:59 字数 2670 浏览 3 评论 0原文

我从我的 GAE Python 应用程序中的这行代码中收到 PicklingError:

deferred.defer(email_voters_begin, ekey, voter_list)

三个参数是:

  • email_voters_begin -- 一个 Python 函数,例如位于 0x1035d4488 的函数 email_voters_begin
  • 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 属性的实体。我不认为任何 BlobInfo 对象都会成为 pickle 的一部分,但错误表明其中包含一个。

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

我对如何调试这个感到困惑,任何想法将不胜感激。

I'm getting a PicklingError from this line of code in my GAE Python app:

deferred.defer(email_voters_begin, ekey, voter_list)

The three arguments are:

  • email_voters_begin -- A Python function, eg., function email_voters_begin at 0x1035d4488
  • ekey -- A key to an entity I defined, eg., prints as agdvcGF2b3Rlcg4LEghFbGVjdGlvbhgCDA
  • voter_list -- A list of objects I defined, eg., [models.Voter object at 0x103d3d310, ... ]

When this line executes as part of my tests (with webtest and nosegae), I get the following error:

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

Note that the Voter entities passed in deferred.defer() do not have a BlobReference property, but the Voter entities do have a ReferenceProperty to another entity that does have a BlobReference property. I wouldn't think that any BlobInfo objects would be part of the pickle but the error suggests one is being included.

This error does not occur when I run the same code from a browser window using the dev server.

I'm stumped as how to debug this and any ideas would be greatly appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月光色 2025-01-04 20:50:59

发生这种情况的原因可能是您已检索至少一个 Voter 对象的 ReferenceProperty。一旦取消引用 ReferenceProperty,模型实例就会缓存它。 Pickling 也会腌制任何缓存的对象,因此它会尝试序列化 Voter 实例、引用的实例及其 BlobInfo

一般来说,正如 Skirmantas 指出的那样,将模型实例传递给 deferred 通常不是一个好主意。如果可能,请发送密钥,如果没有,请将实例序列化到协议缓冲区并发送它们。

This is likely occurring because you've retrieved the ReferenceProperty on at least one of the Voter objects. Once you dereference a ReferenceProperty, the model instance caches it. Pickling pickles any cached objects too, so it attempts to serialize the Voter instance, the referenced instance, and its BlobInfo.

In general, as Skirmantas points out, it's usually a bad idea to pass model instances to deferred. Where possible, send keys, and if not, serialize the instances to Protocol Buffers and send those instead.

柏拉图鍀咏恒 2025-01-04 20:50:59

您永远不应该将模型实例传递给延迟模型。请改用密钥:

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)

You should never pass instances of models to a deferred. Use keys instead:

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

In your email_voters_begin:

def email_voters_begin(ekey, voters_keys):
    voter_list = models.Voter.get(voters_keys)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文