替换 Python 多处理库中的 pickle

Replace pickle in Python multiprocessing lib

我需要执行下面的代码(Python 3.5 中我的真实代码库的简化版本):

import multiprocessing
def forever(do_something=None):
    while True:
        do_something()

p = multiprocessing.Process(target=forever, args=(lambda: print("do  something"),))
p.start()

为了创建新进程 Python 需要 pickle 函数和作为目标传递的 lambda。 不幸的是 pickle 无法序列化 lambda 并且输出是这样的:

_pickle.PicklingError: Can't pickle <function <lambda> at 0x00C0D4B0>: attribute lookup <lambda> on __main__ failed

我发现 cloudpickle 它可以序列化和反序列化 lambda 和闭包,使用与 pickle 相同的接口。

如何强制 Python 多处理模块使用 cloudpickle 而不是 pickle?

显然破解标准库多处理的代码不是一种选择!

谢谢

查理

尝试multiprocess。它是 multiprocessing 的一个分支,它使用 dill 序列化程序而不是 pickle -- 分支中没有其他变化。

我是作者。几年前我遇到了和你一样的问题,最终我决定破解标准库是我唯一的选择,因为 multiprocessing 中的一些 pickle 代码是在 C++ 中。

>>> import multiprocess as mp
>>> p = mp.Pool()
>>> p.map(lambda x:x**2, range(4))
[0, 1, 4, 9]
>>> 

如果你愿意做一点猴子补丁,一个快速的解决办法是分出 pickle.Pickler:

import pickle
import cloudpickle
pickle.Pickler = cloudpickle.Pickler

或者,在更新的 Python 版本中 _pickle.Pickle 被引入,

from multiprocessing import reduction
import cloudpickle
reduction.ForkingPickler = cloudpickle.Pickler

只需确保在导入之前执行此操作 multiprocessing。这是一个完整的例子:

import pickle
import cloudpickle
pickle.Pickler = cloudpickle.Pickler

import multiprocessing as mp
mp.set_start_method('spawn', True)

def procprint(f):
    print(f())

if __name__ == '__main__':
    p = mp.Process(target=procprint, args=(lambda: "hello",))
    p.start()
    p.join()

顺便说一句,如果您的启动方法是 fork,您将不需要执行任何这些操作,因为有了 fork,一开始就不需要 pickle。

我站在同样的问题面前。所以我做了一个小模块,让 pythons mp 可以吃 lambdas。

如果你有很多不同的不可腌制的东西,我也建议使用莳萝或 cloudpickle。

https://github.com/cloasdata/lambdser

pip install lambdser