我在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>
......所以:显然我不能腌制纯净的物体,但如果它是字典的一部分我可以腌制它?有什么不同?我很难理解什么可以腌制什么,什么不能腌制,这对我来说非常困惑。
答案 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
,有几个被腌制的物品......
dict
(D2
)lambda
(F1
)F2
s)lambda
(Co
)__dict__
(D2
)__main__
__dict__
(即globals()
)(D3
)所以,腌制dict
很容易......但如果里面的东西不能被腌制,那么dict
就不能被腌制了。