只有在字典的一部分时才可以腌制对象吗?

时间:2015-09-18 16:15:53

标签: python-2.7 pickle

我在Python 2.7.6中有一个类实例(称为case),是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>

......所以:显然我不能腌制纯净的物体,但如果它是字典的一部分我可以腌制它?有什么不同?我很难理解什么可以腌制什么,什么不能腌制,这对我来说非常困惑。

1 个答案:

答案 0 :(得分: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,打开pickle trace,这样我们就可以看到序列化程序所采用的路径。 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,有几个被腌制的物品......

  • 封闭的dictD2
  • lambdaF1
  • 几个辅助函数(F2 s)
  • 来自lambdaCo
  • 的代码对象
  • lambda的__dict__D2
  • __main__ __dict__(即globals())(D3

所以,腌制dict很容易......但如果里面的东西不能被腌制,那么dict就不能被腌制了。