我假设多处理包使用pickle在进程之间发送东西。但是,pickle会关注对象的__getstate__
和__setstate__
方法。多处理似乎忽略了它们。它是否正确?我困惑了吗?
要复制,请安装docker,然后键入命令行
$ docker run python:3.4 python -c "import pickle
import multiprocessing
import os
class Tricky:
def __init__(self,x):
self.data=x
def __setstate__(self,d):
self.data=10
def __getstate__(self):
return {}
def report(ar,q):
print('running report in pid %d, hailing from %d'%(os.getpid(),os.getppid()))
q.put(ar.data)
print('module loaded in pid %d, hailing from pid %d'%(os.getpid(),os.getppid()))
if __name__ == '__main__':
print('hello from pid %d'%os.getpid())
ar = Tricky(5)
q = multiprocessing.Queue()
p = multiprocessing.Process(target=report, args=(ar, q))
p.start()
p.join()
print(q.get())
print(pickle.loads(pickle.dumps(ar)).data)"
你应该得到像
这样的东西module loaded in pid 1, hailing from pid 0
hello from pid 1
running report in pid 5, hailing from 1
5
10
我原本以为它会是“10”“10”而是“5”“10”。这意味着什么?
(注意:根据用户3667217 的建议编辑符合编程指南的代码)
答案 0 :(得分:4)
多处理模块可以启动以下三种方式之一:spawn,fork或forkserver。默认情况下,在unix上,它会分叉。这意味着在新流程诞生的那一刻,没有必要腌制已装入ram的任何东西。
如果您需要更直接地控制叉子的发生方式,则需要将启动设置更改为spawn。为此,请创建上下文
ctx=multiprocessing.get_context('spawn')
并通过调用multiprocessing.foo()
替换对ctx.foo()
的所有来电。当你这样做时,每个新进程都是作为一个新的python实例诞生的;发送到它的所有内容都将通过pickle发送,而不是直接memcopy。
答案 1 :(得分:1)
提醒:当您使用多处理时,您需要在'if __name__ == '__main__':
子句中启动一个流程:(请参阅programming guidelines)
import pickle
import multiprocessing
class Tricky:
def __init__(self,x):
self.data=x
def __setstate__(self, d):
print('setstate happening')
self.data = 10
def __getstate__(self):
return self.data
print('getstate happening')
def report(ar,q):
q.put(ar.data)
if __name__ == '__main__':
ar = Tricky(5)
q = multiprocessing.Queue()
p = multiprocessing.Process(target=report, args=(ar, q))
print('now starting process')
p.start()
print('now joining process')
p.join()
print('now getting results from queue')
print(q.get())
print('now getting pickle dumps')
print(pickle.loads(pickle.dumps(ar)).data)
在Windows上,我看到了
now starting process
now joining process
setstate happening
now getting results from queue
10
now getting pickle dumps
setstate happening
10
在Ubuntu上,我看到了:
now starting process
now joining process
now getting results from queue
5
now getting pickle dumps
getstate happening
setstate happening
10
我想这应该回答你的问题。 multiprocess
在Windows上调用__setstate__
方法,但在Linux上不调用pickle.dumps
方法。在Linux上,当您致电__getstate__
时,请先致电__setstate__
,然后致电p + Getauto(txtSearch.Text)
。看到多处理模块在不同平台上的表现方式不同,这很有意思。