我在使用multiprocessing
模块(python 2.7,Linux)时尝试共享数据,使用略有不同的代码时得到的结果不同:
import os
import time
from multiprocessing import Process, Manager
def editDict(d):
d[1] = 10
d[2] = 20
d[3] = 30
pnum = 3
m = Manager()
第一版:
mlist = m.list()
for i in xrange(pnum):
mdict = m.dict()
mlist.append(mdict)
p = Process(target=editDict,args=(mdict,))
p.start()
time.sleep(2)
print 'after process finished', mlist
这会产生:
过程结束后[{1:10,2:20,3:30},{1:10,2:20,3:30},{1:10,2:20,3:30} < / p>
第二版:
mlist = m.list([m.dict() for i in xrange(pnum)]) # main difference to 1st version
for i in xrange(pnum):
p = Process(target=editDict,args=(mlist[i],))
p.start()
time.sleep(2)
print 'after process finished', mlist
这会产生:
过程完成后[{},{},{}]
我不明白为什么结果如此不同。
答案 0 :(得分:10)
这是因为您第二次通过列表索引访问变量,而第一次传递实际变量。如multiprocessing docs中所述:
对dict和列表代理中的可变值或项的修改不会通过管理器传播,因为代理无法知道其值或项被修改的时间。
这意味着,要跟踪容器(字典或列表)中更改的项目,必须在每次编辑后重新分配它们。考虑以下更改(出于解释目的,我并未声称这是干净的代码):
def editDict(d, l, i):
d[1] = 10
d[2] = 20
d[3] = 30
l[i] = d
mlist = m.list([m.dict() for i in xrange(pnum)])
for i in xrange(pnum):
p = Process(target=editDict,args=(mlist[i], mlist, i,))
p.start()
如果您现在打印mlist
,您会看到它与第一次尝试的输出相同。重新分配将允许容器代理再次跟踪更新的项目。
在这种情况下,您的主要问题是dict
代理中有list
(代理):管理员不会注意到包含容器的更新,因此没有你期望它有所改变。请注意,字典本身将在第二个示例中更新,但由于管理器未同步,您只是看不到它。