什么时候可以腌制Python对象

时间:2015-04-28 14:28:47

标签: python multiprocessing pickle

我使用多处理模块在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;。

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

4 个答案:

答案 0 :(得分:7)

来自docs

  

可以腌制以下类型:

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

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

答案 1 :(得分:3)

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

泡菜的规则的根源(在我的头顶):

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