我使用多处理模块在Python中进行了大量的并行处理。我知道某些对象可以被pickle(因此作为multi-p中的参数传递)而其他对象则不能。 E.g。
class abc():
pass
a=abc()
pickle.dumps(a)
'ccopy_reg\n_reconstructor\np1\n(c__main__\nabc\np2\nc__builtin__\nobject\np3\nNtRp4\n.'
但是我的代码中有一些更大的类(十几种方法,或者等等),而且会发生这种情况:
a=myBigClass()
pickle.dumps(a)
Traceback (innermost last):
File "<stdin>", line 1, in <module>
File "/usr/apps/Python279/python-2.7.9-rhel5-x86_64/lib/python2.7/copy_reg.py", line 70, in _reduce_ex
raise TypeError, "can't pickle %s objects" % base.__name__
TypeError: can't pickle file objects
它不是文件对象,但在其他时候,我会收到其他基本上说的消息:&#34;我无法腌制这个&#34;。
那么规则是什么?字节数?层次深度?月相?
答案 0 :(得分:7)
来自docs:
可以腌制以下类型:
None
,True
和False
- 整数,长整数,浮点数,复数
- 普通和Unicode字符串
- 仅包含可选对象的元组,列表,集和词典
- 在模块顶层定义的函数
- 在模块顶层定义的内置函数
- 在模块顶层定义的类
- 此类的实例
__dict__
或调用__getstate__()
的结果是可选择的(有关详细信息,请参阅pickle协议一节)。尝试腌制不可摧毁的对象会引发
PicklingError
例外;当发生这种情况时,可能有一个未指定数量的字节 已经写入底层文件。试图腌制高度 递归数据结构可能超过最大递归深度,a 在这种情况下,我会提出RuntimeError
。你可以小心地提出这个 限制为sys.setrecursionlimit()
。
答案 1 :(得分:3)
我是dill
作者。有一个相当全面的清单列出了什么泡菜和什么不是dill
的一部分。它可以在每个版本的Python 2.5-3.4上运行,并通过更改一个标志来调整dill
的泡菜或含pickle
的泡菜。请参阅here和here。
泡菜的规则的根源(在我的头顶):
__main__
与导入函数中定义的函数? [然后,是的] __getstate__
和__setstate__
规则? [然后,是的] Frame
对象(即依赖于GIL和全局执行堆栈)?迭代器现在是一个例外,通过在重新排列时“重放”迭代器。 [然后,没有] __init__
路径操作中定义)? [然后,没有] 因此,(5)现在不像过去那样流行,但在pickle
的语言中仍然有一些持久的影响。 dill
,在大多数情况下,删除(1),(2)和(5) - 但仍然受到(3)和(4)的影响。
我可能会忘记别的东西,但我认为一般来说这些是潜在的规则。
某些模块(如multiprocessing
)会注册一些对其功能很重要的对象。 dill
注册了该语言中的大多数对象。
dill
的{{1}}分叉是必需的,因为multiprocessing
使用multiprocessing
,而cPickle
只能扩充纯Python修补注册表。如果您有耐心,可以查看dill
中的所有相关copy_reg
函数,并将它们应用到dill
模块中,您将获得更强大的功能cPickle
{1}}。我找到了一个简单的(读取:单行)方法来为multiprocessing
执行此操作,但不是pickle
。
答案 2 :(得分:2)
一般的经验法则是“逻辑”对象可以被腌制,但“资源”对象(文件,锁)不能,因为持久化/克隆它们是没有意义的。
答案 3 :(得分:2)
除了icedtrees的回答,也直接来自docs,您可以使用特殊方法自定义和控制类实例被腌制和取消的方式:object.__getnewargs_ex__()
,object.__getnewargs__()
,object.__getstate__()
,object.__setstate__(state)