__main__
通过导入和使用该模块中可用的方法,您可以更好地处理全局对象。这就是dill所做的,以便在 python 中序列化几乎任何东西。基本上,当 dill 序列化一个交互式定义的函数时,它会__main__
在序列化和反序列化端使用一些名称修饰,从而__main__
生成一个有效的模块。
>>> import dill
>>>
>>> def bar(x):
... return foo(x) + x
...
>>> def foo(x):
... return x**2
...
>>> bar(3)
12
>>>
>>> _bar = dill.loads(dill.dumps(bar))
>>> _bar(3)
12
实际上,dill 将它的类型注册到pickle
注册表中,所以如果您有一些使用的黑盒代码pickle
并且您不能真正编辑它,那么只需导入 dill 就可以神奇地使其工作,而无需猴子修补第 3 方代码。
或者,如果您希望将整个解释器会话作为“python 图像”发送,dill 也可以这样做。
>>> # continuing from above
>>> dill.dump_session('foobar.pkl')
>>>
>>> ^D
dude@sakurai>$ python
Python 2.7.5 (default, Sep 30 2013, 20:15:49)
[GCC 4.2.1 (Apple Inc. build 5566)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import dill
>>> dill.load_session('foobar.pkl')
>>> _bar(3)
12
您可以轻松地将图像通过 ssh 发送到另一台计算机,然后从您离开的地方开始,只要存在 pickle 的版本兼容性以及关于 python 更改和正在安装的东西的常见警告。
我实际上使用 dill 序列化对象并使用并行 python、 multiprocessing 和mpi4py跨并行资源发送它们。我将这些方便地汇总到pathos包中(以及用于 MPI 的pyinamap
),它为不同的并行批处理后端提供了统一的接口。
>>> # continued from above
>>> from pathos.multiprocessing import ProcessingPool as Pool
>>> Pool(4).map(foo, range(10))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>>
>>> from pyina.launchers import MpiPool
>>> MpiPool(4).map(foo, range(10))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
还有非阻塞和迭代映射以及非平行管道连接。我也有一个 pathos 模块pp
,但是对于__main__
. 我正在努力改进它。如果你愿意,可以在 github 上 fork 代码并帮助pp
改进__main__
. pp
不能很好地腌制的原因是pp
它通过使用临时文件对象和读取解释器会话的历史来进行序列化技巧......所以它不会以与多处理或 mpi4py 相同的方式序列化对象。我有一个 dill 模块dill.source
,可以无缝地执行与使用相同类型的酸洗pp
,但它是相当新的。