【问题标题】:Can pickle object only when part of dictionary?只有当字典的一部分时才能腌制对象?
【发布时间】:2015-09-18 16:15:53
【问题描述】:

我有一个类实例(称为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>

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

【问题讨论】:

  • (1) 您应该展示您的代码,以便其他人可以轻松提供帮助,以及 (2) 您可能想尝试dill 而不是cPickle。我敢打赌,使用dill 将解决您的酸洗错误。大多数对象不能cPickle腌制,但是dill可以腌制python中的大多数对象。
  • 我正在使用的实际课程太大而无法放在这里,无论如何我都不允许展示它们。不过,我不知道哪个方面很重要。我设法用莳萝腌制了一个实例,而不是另一个(抱怨Can't pickle &lt;type 'numpy.int64'&gt;: it's not the same object as numpy.int64),因为某些数字的所有实例都应该相同! => 我希望有人能告诉我在哪里看,例如为什么字典会腌制,但它的组件却不会,一开始
  • 是的,这是一个已知问题,并且不起作用,因为numpy.int64 不是int……它是部分用 C 构建的类的实例……但更重要的是, numpy.int64 在导入中有一些命名空间修改,dill 无法回溯和解决。
  • 这是否意味着如果我想腌制东西,我不能使用 numpy ints?花车效果更好吗(我有很多)?
  • 好吧,我找到了一个解决方案,删除实例的一个属性(它是另一个类的实例),然后使用 dill 保存实例的字典(仍然无法在实例上工作) ,并将类更改为具有从字典中重建实例的功能。 ——我也无法重建原来的问题,所以这个问题现在有点没用了……我应该删除它吗?有标准流程吗?

标签: python-2.7 pickle


【解决方案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 跟踪,这样我们就可以看到序列化程序采用的路径。 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)被腌制,而dict中的lambda,有几个对象被腌制......

  • 封闭的dict (D2)
  • lambda (F1)
  • 几个辅助函数(F2s)
  • 来自lambda (Co) 的代码对象
  • lambda 的 __dict__ (D2)
  • __main____dict__(即globals())(D3

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

【讨论】:

  • 感谢您的解释。它确实使事情更清楚。有趣的是,我不能单独腌制一个对象,但当它是字典的一部分时显然可以。 -- 我目前正在尝试找出如何隔离问题
  • @Zak:你可能想试试dill.detect中的pickle调试方法,见:stackoverflow.com/questions/17872056/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-06
  • 2013-05-02
  • 2016-03-27
  • 2018-06-15
  • 1970-01-01
  • 2011-05-04
  • 2018-10-30
相关资源
最近更新 更多