您可以通过导入__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 就可以神奇地使它工作而无需猴子补丁第三方代码。
或者,如果您希望将整个解释器会话作为“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 序列化对象并使用 parallel python、多处理和 mpi4py 在并行资源之间发送它们。我将这些方便地汇总到 pathos 包中(以及用于 MPI 的 pyina),它为不同的并行批处理后端提供了统一的 map 接口。
>>> # 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]
还有非阻塞和迭代映射以及非平行管道连接。我还有一个用于pp 的 pathos 模块,但是,它对于__main__ 中定义的函数有些不稳定。我正在努力改进它。如果您愿意,请 fork the code on github 并帮助使 pp 更好地用于 __main__ 中定义的函数。 pp 不能很好地腌制的原因是 pp 通过使用临时文件对象和读取解释器会话的历史来实现序列化技巧......所以它不会以与多处理或 mpi4py 相同的方式序列化对象。我有一个 dill 模块 dill.source 可以无缝地执行 pp 使用的相同类型的酸洗,但它是相当新的。