在流程

时间:2017-11-29 09:00:16

标签: python multiprocessing python-multiprocessing

我无法在Python2.7中使用多处理的进程之间传递dict的dict

from multiprocessing import Process, Manager

class TestProcess(Process):
    def __init__(self, d, w):
        super(TestProcess, self).__init__()
        self.daemon = True
        self.d = d
        self.w = w

    def run(self):
        self.d['a'][self.w] = self.w


class Test(object):
    def __init__(self):
        manager = Manager()
        self.d = manager.dict()
        self.d['a'] = {}

        p = TestProcess(d=self.d, w=1)
        p.start()
        p.join()

        p = TestProcess(d=self.d, w=2)
        p.start()
        p.join()

    def show(self):
        print(self.d)

if __name__ == '__main__':

    t=Test()
    t.show()

期待结果:{'a':{1:1,2:2}},但得到{'a':{}}而不是

1 个答案:

答案 0 :(得分:1)

使嵌套字典也成为代理对象:

manager = Manager()
self.d = manager.dict()
self.d['a'] = manager.dict() 

或检索self.d['a'],改变该对象并将其设置回来:

a = self.d['a']
a[self.w] = self.w
self.d['a'] = a

self.d不是常规词典;它包含一个字典来跟踪对象本身的突变,但是与键'a'相关联的不是这样的对象,因此未检测到该对象的突变,并且更改没有与父流程沟通。

如果您要使用self.d['a'][self.w] = self.w,那么self.d['a'] = self.d['a']后者将从父进程中检索仍为空的字典,并将self.d['a']设置回该空宾语;您首先创建对远程可变嵌套字典的本地引用,以确保您正确地告诉父进程正确设置它。

来自文档的Proxy Objects section

  

如果标准(非代理)列表或dict对象包含在引用对象中,则对这些可变值的修改将不会通过管理器传播,因为代理无法知道何时修改其中包含的值。但是,将值存储在容器代理中(在代理对象上触发__setitem__)确实会传播通过管理器,因此为了有效地修改这样的项,可以将修改后的值重新分配给容器代理:

# create a list proxy and append a mutable object (a dictionary)
lproxy = manager.list()
lproxy.append({})
# now mutate the dictionary
d = lproxy[0]
d['a'] = 1
d['b'] = 2
# at this point, the changes to d are not yet synced, but by
# updating the dictionary, the proxy is notified of the change
lproxy[0] = d