使用python多处理模块中的Manager()共享数据

Hon*_*Zhu 8 python multiprocessing

我在使用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()
Run Code Online (Sandbox Code Playgroud)

第一版:

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
Run Code Online (Sandbox Code Playgroud)

这会产生:

过程结束后[{1:10,2:20,3:30},{1:10,2:20,3:30},{1:10,2:20,3:30}]

第2版​​:

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
Run Code Online (Sandbox Code Playgroud)

这会产生:

处理完成后[{},{},{}]

我不明白为什么结果如此不同.

jro*_*jro 10

这是因为您第二次通过列表索引访问变量,而第一次传递实际变量.如多处理文档中所述:

对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()
Run Code Online (Sandbox Code Playgroud)

如果您现在要打印mlist,您将看到它与您的第一次尝试具有相同的输出.重新分配将允许容器代理再次跟踪更新的项目.

在这种情况下,您的主要问题是您在dict代理中有一个(代理)list:管理员不会注意到包含容器的更新,因此没有您期望它具有的更改.请注意,字典本身将在第二个示例中更新,但由于管理器未同步,您只是看不到它.