PicklingError: Can't pickle <class ...>: это не тот же объект, что и ... в GAE - PullRequest
1 голос
/ 23 января 2012

Я получаю PicklingError из этой строки кода в моем приложении GAE Python:

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, ...]

Когда эта строка выполняется как часть моих тестов (с веб-тестом и носом), я получаю следующую ошибку:

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 будут частью рассола, но ошибка предполагает, что один из них включен.

Эта ошибка не возникает, когда я запускаю тот же код из окна браузера с помощью сервера dev.

Я в тупик, как отлаживать это, и любые идеи будут с благодарностью.

Ответы [ 2 ]

1 голос
/ 24 января 2012

Это, вероятно, происходит, потому что вы получили ReferenceProperty хотя бы для одного из объектов избирателя.После разыменования ReferenceProperty экземпляр модели кэширует его.Pickling также выбирает любые кэшированные объекты, поэтому он пытается сериализовать экземпляр Voter, указанный экземпляр и его BlobInfo.

В общем, как указывает Скирмантас, обычно плохая идея передать модельслучаи откладываются.По возможности отправляйте ключи, а если нет, сериализуйте экземпляры в буферы протокола и отправляйте их вместо этого.

1 голос
/ 23 января 2012

Вы никогда не должны передавать экземпляры моделей отложенному. Вместо этого используйте ключи:

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)
...