什么时候可以 pickle Python 对象
When can a Python object be pickled
我正在 Python 使用多处理模块进行大量并行处理。我知道某些对象可以被 pickle(因此在 multi-p 中作为参数传递)而其他对象不能。例如
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
它不是文件对象,但在其他时候,我会收到其他消息,基本上是:"I can't pickle this".
那么规则是什么?字节数?层级深度?月相?
来自docs:
The following types can be pickled:
None
, True
, and False
- integers, long integers, floating point numbers, complex numbers
- normal and Unicode strings
- tuples, lists, sets, and dictionaries containing only picklable objects
- functions defined at the top level of a module
- built-in functions defined at the top level of a module
- classes that are defined at the top level of a module
- instances of such classes whose
__dict__
or the result of calling __getstate__()
is picklable (see section The pickle protocol for details).
Attempts to pickle unpicklable objects will raise the PicklingError
exception; when this happens, an unspecified number of bytes may have
already been written to the underlying file. Trying to pickle a highly
recursive data structure may exceed the maximum recursion depth, a
RuntimeError
will be raised in this case. You can carefully raise this
limit with sys.setrecursionlimit()
.
一般的经验法则是 "logical" 对象可以被 pickle,但是 "resource" 对象(文件,锁)不能,因为 persist/clone 它们没有意义.
除了 icedtrees 的答案,也直接来自 docs,您可以使用特殊方法自定义和控制 class 实例的 pickle 和 unpicked 方式:object.__getnewargs_ex__()
, object.__getnewargs__()
, object.__getstate__()
, object.__setstate__(state)
我是 dill
的作者。作为 dill
的一部分,有一个相当全面的清单,其中列出了泡菜和不泡菜的内容。它可以是每个 Python 2.5–3.4 版本的 运行,并通过更改一个标志来调整用 dill
腌制的内容或用 pickle
腌制的内容。参见 here and here。
泡菜规则的根源是什么(我想不起来了):
- 你能通过引用捕获对象的状态吗(即一个
__main__
中定义的函数与导入的函数)? [那么,是的]
- 给定对象类型是否存在通用
__getstate__
和 __setstate__
规则? [那么,是的]
- 它是否依赖于
Frame
对象(即依赖于 GIL 和全局执行堆栈)?迭代器现在是一个例外,"replaying" unpickling 上的迭代器。 [那么,没有]
- 对象实例是否指向错误的 class 路径(即由于在闭包、C 绑定或其他
__init__
路径操作中定义)? [那么,没有]
- Python 认为允许这样做是危险的吗? [那么,没有]
因此,(5) 现在不像以前那么流行了,但在 pickle
的语言中仍然有一些持久的影响。 dill
,在大多数情况下,删除了 (1)、(2) 和 (5) – 但仍然受到 (3) 和 (4) 的影响。
我可能忘记了其他东西,但我认为一般来说这些是基本规则。
像multiprocessing
这样的某些模块注册了一些对其功能很重要的对象。 dill
注册了该语言中的大多数对象。
multiprocessing
的 dill
分支是必需的,因为 multiprocessing
使用 cPickle
,而 dill
只能扩充纯 Python酸洗注册表。如果你有耐心,你可以通过 dill
中所有相关的 copy_reg
函数,并将它们应用到 cPickle
模块,你会得到一个更 pickle-capable multiprocessing
。我找到了一种简单的(阅读:一个班轮)方法来为 pickle
执行此操作,但不是 cPickle
.
我正在 Python 使用多处理模块进行大量并行处理。我知道某些对象可以被 pickle(因此在 multi-p 中作为参数传递)而其他对象不能。例如
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
它不是文件对象,但在其他时候,我会收到其他消息,基本上是:"I can't pickle this".
那么规则是什么?字节数?层级深度?月相?
来自docs:
The following types can be pickled:
None
,True
, andFalse
- integers, long integers, floating point numbers, complex numbers
- normal and Unicode strings
- tuples, lists, sets, and dictionaries containing only picklable objects
- functions defined at the top level of a module
- built-in functions defined at the top level of a module
- classes that are defined at the top level of a module
- instances of such classes whose
__dict__
or the result of calling__getstate__()
is picklable (see section The pickle protocol for details).Attempts to pickle unpicklable objects will raise the
PicklingError
exception; when this happens, an unspecified number of bytes may have already been written to the underlying file. Trying to pickle a highly recursive data structure may exceed the maximum recursion depth, aRuntimeError
will be raised in this case. You can carefully raise this limit withsys.setrecursionlimit()
.
一般的经验法则是 "logical" 对象可以被 pickle,但是 "resource" 对象(文件,锁)不能,因为 persist/clone 它们没有意义.
除了 icedtrees 的答案,也直接来自 docs,您可以使用特殊方法自定义和控制 class 实例的 pickle 和 unpicked 方式:object.__getnewargs_ex__()
, object.__getnewargs__()
, object.__getstate__()
, object.__setstate__(state)
我是 dill
的作者。作为 dill
的一部分,有一个相当全面的清单,其中列出了泡菜和不泡菜的内容。它可以是每个 Python 2.5–3.4 版本的 运行,并通过更改一个标志来调整用 dill
腌制的内容或用 pickle
腌制的内容。参见 here and here。
泡菜规则的根源是什么(我想不起来了):
- 你能通过引用捕获对象的状态吗(即一个
__main__
中定义的函数与导入的函数)? [那么,是的] - 给定对象类型是否存在通用
__getstate__
和__setstate__
规则? [那么,是的] - 它是否依赖于
Frame
对象(即依赖于 GIL 和全局执行堆栈)?迭代器现在是一个例外,"replaying" unpickling 上的迭代器。 [那么,没有] - 对象实例是否指向错误的 class 路径(即由于在闭包、C 绑定或其他
__init__
路径操作中定义)? [那么,没有] - Python 认为允许这样做是危险的吗? [那么,没有]
因此,(5) 现在不像以前那么流行了,但在 pickle
的语言中仍然有一些持久的影响。 dill
,在大多数情况下,删除了 (1)、(2) 和 (5) – 但仍然受到 (3) 和 (4) 的影响。
我可能忘记了其他东西,但我认为一般来说这些是基本规则。
像multiprocessing
这样的某些模块注册了一些对其功能很重要的对象。 dill
注册了该语言中的大多数对象。
multiprocessing
的 dill
分支是必需的,因为 multiprocessing
使用 cPickle
,而 dill
只能扩充纯 Python酸洗注册表。如果你有耐心,你可以通过 dill
中所有相关的 copy_reg
函数,并将它们应用到 cPickle
模块,你会得到一个更 pickle-capable multiprocessing
。我找到了一种简单的(阅读:一个班轮)方法来为 pickle
执行此操作,但不是 cPickle
.