替换 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
我需要执行下面的代码(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