【发布时间】:2019-11-16 15:58:42
【问题描述】:
在 Windows 上使用 Python 的 multiprocessing 将需要许多参数在传递给子进程时是“可挑选的”。
import multiprocessing
class Foobar:
def __getstate__(self):
print("I'm being pickled!")
def worker(foobar):
print(foobar)
if __name__ == "__main__":
# Uncomment this on Linux
# multiprocessing.set_start_method("spawn")
foobar = Foobar()
process = multiprocessing.Process(target=worker, args=(foobar, ))
process.start()
process.join()
可腌制性
确保代理方法的参数是可挑选的。
[...]
比pickle/unpickle更好继承
当使用 spawn 或 forkserver 启动方法时,
multiprocessing中的许多类型需要是可挑选的,以便子进程可以使用它们。但是,通常应该避免使用管道或队列将共享对象发送到其他进程。相反,您应该安排程序,以便需要访问在其他地方创建的共享资源的进程可以从祖先进程继承它。[...]
更易腌制
确保
Process.__init__()的所有参数都是可提取的。此外,如果您将Process子类化,请确保在调用Process.start方法时实例是可挑选的。
但是,我注意到“multiprocessingpickle”和标准 pickle 模块之间的两个主要区别,我无法理解所有这些。
multiprocessing.Queue() 不是“可挑选”的,但可以传递给子进程
import pickle
from multiprocessing import Queue, Process
def worker(queue):
pass
if __name__ == "__main__":
queue = Queue()
# RuntimeError: Queue objects should only be shared between processes through inheritance
pickle.dumps(queue)
# Works fine
process = Process(target=worker, args=(queue, ))
process.start()
process.join()
如果在“main”中定义,则不可腌制
import pickle
from multiprocessing import Process
def worker(foo):
pass
if __name__ == "__main__":
class Foo:
pass
foo = Foo()
# Works fine
pickle.dumps(foo)
# AttributeError: Can't get attribute 'Foo' on <module '__mp_main__' from 'C:\\Users\\Delgan\\test.py'>
process = Process(target=worker, args=(foo, ))
process.start()
process.join()
如果multiprocessing内部不使用pickle,那么这两种序列化对象方式的内在区别是什么?
另外,在多处理的上下文中,“继承”是什么意思?我应该怎么喜欢它而不是泡菜?
【问题讨论】:
标签: python multiprocessing pickle