2011-07-05 2 views
4

Я взял чей-то код для довольно крупного проекта. Я пытаюсь сохранить состояние программы, и есть один массивный объект, который хранит почти все другие объекты. Я пытаюсь протравить этот объект, но я получаю эту ошибку:Как найти источник ошибки в Python Pickle на массивном объекте

pickle.PicklingError: Can't pickle : it's not found as builtin.module

Из того, что я могу найти на Google, это потому, что где-то я импортировать что-то за пределами питона инициализации, или атрибут класса ссылки на модуль. Итак, у меня есть два вопроса:

  1. Может кто-нибудь подтвердить, что именно поэтому эта ошибка дается? Я ищу правильные вещи в своем коде?

  2. Есть ли способ найти, какая строка элемента кода/объекта вызывает трудности при рассоле? Трассировка только дает линию в мариновании, где происходит ошибка, а не линия продуваемого объекта.

ответ

10

2) Вы можете создать подкласс pickle.Pickler и обезьяна-патч, чтобы это показать журнал, что это травление. Это должно облегчить отслеживание проблемы.

import pickle 
class MyPickler (pickle.Pickler): 
    def save(self, obj): 
     print 'pickling object', obj, 'of type', type(obj) 
     pickle.Pickler.save(self, obj) 

Это будет работать только с реализацией Python pickle.Pickler. В Python 3.x модуль pickle использует реализацию C по умолчанию, версия Pickler с чистым Python называется _Pickler.

# Python 3.x 
import pickle 
class MyPickler (pickle._Pickler): 
    def save(self, obj): 
     print ('pickling object {0} of type {1}'.format(obj, type(obj)) 
     pickle._Pickler.save(self, obj) 
+0

хорошо, мне нравится это лучше, чем мой ответ, потому что он идентифицирует проблемный объект, даже если он имеет несколько уровней. Чтобы найти ** все ** незащищенные объекты в вашем массивном объекте, оберните это в блок 'try' ...' except'. – RoundTower

+0

Спасибо! Я начал в cPickle, поэтому я забыл о объекте Pickler. Я попробую это сразу, но это похоже на то, что я ищу – jmite

+0

Работает как шарм! Это менее 2500 строк кода, которые мне нужно просмотреть вручную ... – jmite

1

1) Есть небольшое отличие от того, что вы нашли. Это проблема, вызванная некоторой переменной (атрибутом класса, списком или типом элемента, может быть что угодно), которая ссылается на тип модуля (а не непосредственно на модуль). Этот код должен воспроизвести проблему:

import pickle 
pickle.dumps(type(pickle)) 
1

Как быстро и грязный способ найти то, что атрибут/элемент объекта является причиной проблемы, вы можете попробовать:

for k, v in massiveobject.__dict__.iteritems(): 
    print k 
    pickle.dumps(v) 
3

Нечто подобное существует в dill. Давайте посмотрим на список объектов, и посмотреть, что мы можем сделать:

>>> import dill 
>>> f = open('whatever', 'w') 
>>> f.close() 
>>> 
>>> l = [iter([1,2,3]), xrange(5), open('whatever', 'r'), lambda x:x] 
>>> dill.detect.trace(False) 
>>> dill.pickles(l) 
False 

Ok, dill не удается замариновать список. Так в чем проблема?

>>> dill.detect.trace(True) 
>>> dill.pickles(l) 
T4: <type 'listiterator'> 
False 

Хорошо, первый элемент в списке не рассол. А как насчет остальных?

>>> map(dill.pickles, l) 
T4: <type 'listiterator'> 
Si: xrange(5) 
F2: <function _eval_repr at 0x106991cf8> 
Fi: <open file 'whatever', mode 'r' at 0x10699c810> 
F2: <function _create_filehandle at 0x106991848> 
B2: <built-in function open> 
F1: <function <lambda> at 0x1069f6848> 
F2: <function _create_function at 0x1069916e0> 
Co: <code object <lambda> at 0x105a0acb0, file "<stdin>", line 1> 
F2: <function _unmarshal at 0x106991578> 
D1: <dict object at 0x10591d168> 
D2: <dict object at 0x1069b1050> 
[False, True, True, True] 

Hm. Другие объекты рассоряются просто отлично. Итак, заменим первый объект.

>>> dill.detect.trace(False) 
>>> l[0] = xrange(1,4) 
>>> dill.pickles(l) 
True 
>>> _l = dill.loads(dill.dumps(l)) 

Теперь наш объект соленья. Ну, мы могли бы воспользоваться некоторыми встроенными функциями совместного использования объектов, которые происходят для травления на linux/unix/mac ... так что же более сильная проверка, например, на самом деле трассировка по подпроцессу (например, происходит в окнах)?

>>> dill.check(l)   
[xrange(1, 4), xrange(5), <open file 'whatever', mode 'r' at 0x107998810>, <function <lambda> at 0x1079ec410>] 
>>> 

Нет, список все еще работает ... так что это объект, который может быть успешно отправлен другому процессу.

Теперь, в связи с вашей ошибкой, что все, казалось, игнорировать ...

ModuleType объект не pickleable, и это вызывает у вас ошибку.

>>> import types 
>>> types.ModuleType 
<type 'module'> 
>>> 
>>> import pickle 
>>> pickle.dumps(types.ModuleType) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 1374, in dumps 
    Pickler(file, protocol).dump(obj) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 224, in dump 
    self.save(obj) 
    File "/opt/local/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 "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 748, in save_global 
    (obj, module, name)) 
pickle.PicklingError: Can't pickle <type 'module'>: it's not found as __builtin__.module 

Однако, если мы импортируем dill, она волшебным образом работает.

>>> import dill 
>>> pickle.dumps(types.ModuleType) 
"cdill.dill\n_load_type\np0\n(S'ModuleType'\np1\ntp2\nRp3\n." 
>>> 
Смежные вопросы