2015-09-18 1 views
0

У меня есть экземпляр класса (case), в Python 2.7.6, подкласса от object. Он имеет несколько методов, но также хранит кучу данных. Я бы хотел рассолить эту штуку. Однако, если я пытаюсь «просто сделать это», я получаю сообщение об ошибке:Может ли солить объект только в части словаря?

import cPickle 
saver = cPickle.Pickler(sfile) 
saver.dump(case) 
    File "/usr/lib64/python2.7/copy_reg.py", line 70, in _reduce_ex 
    raise TypeError, "can't pickle %s objects" % base.__name__ 
    TypeError: can't pickle function objects 

Но потом я понял, что я могу замариновать case.__dict__ без проблем, но один из его атрибутов является экземпляром подобного класса! Почему я могу замачивать это, но не это? Так что я попытался следующие:

casedict = {'testcase1':case} 
saver.dump(casedict) 

    <cPickle.Pickler object at 0x6fef398> 

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

+0

(1) вы должны показать свой код, чтобы другие могли легко помочь, и (2) вы можете попробовать 'dill' вместо' cPickle'. Я бы сказал, что использование «укропа» исправит вашу ошибку травления. Большинство объектов ** НЕ МОЖЕТ ** быть маринованными с помощью 'cPickle', однако' dill' может мариновать большинство объектов в python. –

+0

Фактические классы, с которыми я работаю, слишком велики, чтобы вставлять их здесь, и мне все равно не разрешат их показывать. Я не знаю, какой аспект важен. Мне удалось раскрыть один экземпляр с укропом, но не другим (жалуется на '' Can not pickle : это не тот же объект, что и numpy.int64''), когда все экземпляры должны быть одинаковыми для некоторых чисел! => Я надеялся, что кто-то скажет мне, где искать, например. почему словарь будет мариновать, но его компоненты не будут, для начала – Zak

+0

Да, это известная проблема и не работает, потому что «numpy.int64' не является 'int' ... это экземпляр класса, который частично построен в C ... но что более важно,' numpy.int64' имеет некоторое пространство имен в импорте, которое 'dill' не может отменить и решить. –

ответ

1

Посмотрите на маринование dict. Это легко сделать, пока вы не нанесете что-то в него, которое нельзя мариновать.

>>> import pickle 
>>> pickle.dumps({}) 
'(dp0\n.' 
>>> pickle.dumps({'a':1}) 
"(dp0\nS'a'\np1\nI1\ns." 
>>> pickle.dumps({'a':1, 'b':(lambda x:x)}) 
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 649, in save_dict 
    self._batch_setitems(obj.iteritems()) 
    File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/pickle.py", line 663, in _batch_setitems 
    save(v) 
    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 <function <lambda> at 0x104c765f0>: it's not found as __main__.<lambda> 
>>> 

Теперь, давайте использовать dill с рассол след включен, так что мы можем увидеть путь сериализатор берет. dill может сериализовать lambda, так что это не подводит.

>>> import dill 
>>> 
>>> dill.detect.trace(True) 
>>> pickle.dumps({}) 
D2: <dict object at 0x104c3a4b0> 
# D2 
'(dp0\n.' 
>>> pickle.dumps({'a':1}) 
D2: <dict object at 0x104c3a4b0> 
# D2 
"(dp0\nS'a'\np1\nI1\ns." 
>>> pickle.dumps({'a':1, 'b':(lambda x:x)}) 
D2: <dict object at 0x104c3a4b0> 
F1: <function <lambda> at 0x105c729b0> 
F2: <function _create_function at 0x105c0c938> 
# F2 
Co: <code object <lambda> at 0x104e70830, file "<stdin>", line 1> 
F2: <function _unmarshal at 0x105c0c7d0> 
# F2 
# Co 
D3: <dict object at 0x104b95168> 
# D3 
D2: <dict object at 0x105c30280> 
# D2 
# F1 
# D2 
"(dp0\nS'a'\np1\nI1\nsS'b'\np2\ncdill.dill\n_create_function\np3\n(cdill.dill\n_unmarshal\np4\n(S'c\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00\\x01\\x00\\x00\\x00C\\x00\\x00\\x00s\\x04\\x00\\x00\\x00|\\x00\\x00S(\\x01\\x00\\x00\\x00N(\\x00\\x00\\x00\\x00(\\x01\\x00\\x00\\x00t\\x01\\x00\\x00\\x00x(\\x00\\x00\\x00\\x00(\\x00\\x00\\x00\\x00s\\x07\\x00\\x00\\x00<stdin>t\\x08\\x00\\x00\\x00<lambda>\\x01\\x00\\x00\\x00s\\x00\\x00\\x00\\x00'\np5\ntp6\nRp7\nc__main__\n__dict__\nS'<lambda>'\np8\nNN(dp9\ntp10\nRp11\ns." 

Вы можете увидеть пустой dict, просто dict (т.е. D2) маринуется, в то время как с lambda в dict, есть несколько объектов, которые получают маринованные ...

  • вмещающих dict (D2)
  • lambda (F1)
  • несколько вспомогательных функций (F2 ы)
  • код объекта из lambda (Co)
  • лямбда-х __dict__ (D2)
  • __main____dict__ (т.е. globals()) (D3)

Таким образом, травление в dict легко ... но если что внутри не может быть маринованные, то dict не может быть маринованный.

+0

Спасибо за объяснение. Это делает вещи более ясными. Смешной бит заключается в том, что я не мог рассортировать объект автономно, но, видимо, мог, когда он был частью словаря. - В настоящее время я пытаюсь выяснить, как изолировать проблему. – Zak

+0

@ Zak: вы можете попробовать методы отладки pickle в 'dill.detect', см. Http://stackoverflow.com/questions/17872056/ как к регистрации по прибытию, если-объект-это-pickleable/32206955 # 32206955 –

Смежные вопросы