什么时候可以腌制Python对象

Pau*_*son 14 python pickle multiprocessing

我正在使用多处理模块在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.'
Run Code Online (Sandbox Code Playgroud)

但是我的代码中有一些更大的类(十几种方法,或者这样),这种情况发生了:

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
Run Code Online (Sandbox Code Playgroud)

它不是文件对象,但在其他时候,我会得到其他基本上说的消息:"我不能腌制这个".

那么规则是什么?字节数?层次深度?月相?

ice*_*ees 7

来自文档:

可以腌制以下类型:

  • None,TrueFalse
  • 整数,长整数,浮点数,复数
  • 普通和Unicode字符串
  • 仅包含可选对象的元组,列表,集和词典
  • 在模块顶层定义的函数
    • 在模块顶层定义的内置函数
  • 在模块顶层定义的类
  • 这些类的实例__dict__或其调用结果__getstate__()是可选择的(有关详细信息,请参阅pickle协议一节).

尝试腌制不可摧毁的对象会引发PicklingError 异常; 当发生这种情况时,可能已经将未指定数量的字节写入底层文件.尝试挑选高度递归的数据结构可能会超过最大递归深度,RuntimeError在这种情况下会引发一个 .你可以小心地提高这个限制sys.setrecursionlimit().

  • 正如稍后在文档中所述,还可以定义`__reduce__`和`__setstate__`和`__getstate__`方法以使任意对象可选,或使用持久ID来引用全局对象(如文件). (2认同)

Mik*_*rns 7

我是dill作者。有一个相当全面的清单,列出了泡菜和不属于dill. 它可以在每个版本的 Python 2.5-3.4 上运行,并通过更改一个标志来调整使用什么泡菜dill或泡菜pickle。请参阅此处此处

泡菜规则的根源是什么(在我的脑海中):

  1. 您能否通过引用捕获对象的状态(即定义的函数__main__与导入的函数)?[然后,是的]
  2. 给定的对象类型是否存在通用__getstate____setstate__规则?[然后,是的]
  3. 它是否依赖于一个Frame对象(即依赖于 GIL 和全局执行堆栈)?迭代器现在是一个例外,通过在 unpickling 时“重放”迭代器。[然后,没有]
  4. 对象实例是否指向错误的类路径(即由于在闭包、C 绑定或其他__init__路径操作中定义)?[然后,没有]
  5. Python 认为允许这样做是危险的吗?[然后,没有]

因此,(5)现在不像以前那么流行了,但在pickle. dill,在大多数情况下,删除 (1)、(2) 和 (5) – 但仍然受到 (3) 和 (4) 的影响。

我可能忘记了其他一些东西,但我认为总的来说这些是基本规则。

某些模块喜欢multiprocessing注册一些对其功能很重要的对象。dill注册语言中的大多数对象。

dillforkmultiprocessing是必需的,因为multiprocessing使用cPickle, 并且dill只能增加纯 Python 酸洗注册表。你可以,如果你有耐心,通过所有相关copy_reg的功能dill,并将其应用到cPickle模块,你会得到一个更泡菜能力multiprocessing。我找到了一种简单的(阅读:一个班轮)方法来为pickle,但不是cPickle.