Python Multiprocessing - 修改共享字典中的值

Rak*_*ker 1 python dictionary python-multiprocessing

我正在处理一个项目,我将一个进程中的数据解析为一个 python 字典,然后由另一个 python 进程读取,从而创建不同的数据视图。解析的数据来自 worker1 进程处理的传感器。

到目前为止,我可以使用共享字典创建两个进程,并且我最终可以毫无问题地向其中添加值。但是,当我想修改现有值时,我碰到了砖墙。我已经阅读了几个小时的“许多”答案并尝试了解决方案,例如创建一个包含密钥的新对象。例如x = d["key"][1];x = 'newvalue'。只是不起作用。我在 python 3.6 中运行代码,但问题在 2.7 中似乎相似。这是简化版本的代码:

#!/usr/bin/python3
import subprocess,time
from multiprocessing import Process, Manager

def worker1(d):
    d["key"] = []    #Creating empty dict item
    d["key"]+=["hellostack"] #Adding first value
    d["key"]+=[1]    #Adding second value
    print ("from worker1:",d)
    d["key"][1]+=2 #<<<< ISSUE HERE - Modifying second value does nothing
    print ("Now value should be upped!..",d)

def worker2(d):
    while True:
        time.sleep(1)
        print ("from worker 2:",d)

manager = Manager()
d = manager.dict()

worker1 = Process(target=worker1, args=(d,))
worker2 = Process(target=worker2, args=(d,))
worker1.start()
worker2.start()
worker1.join()
worker2.join()
Run Code Online (Sandbox Code Playgroud)

我得到的输出是:

from worker1: {'key': ['hellostack', 1]}
Now value should be upped!.. {'key': ['hellostack', 1]}
from worker 2: {'key': ['hellostack', 1]}
Run Code Online (Sandbox Code Playgroud)

任何人?:o)

编辑:可能的重复,不关注两个单独的进程,也不讨论里面有列表的字典。然而,不可否认的是非常相似,实际上答案让我得到了答案。所以我将暂定。

sch*_*enk 7

这是可变值的副作用以及多处理在进程之间同步数据的方式。

dict你从multiprocessing.Manager得到的是不是某种共享内存。当管理器注意到修改时,它通过消息显式同步到子进程!

它如何通知修改?

简单:只需使用将事物同步到其他进程的代理覆盖 dict 的所有修改方法。你可以看到的代理方法列表这里的Python源代码。

让我们逐行查看您的示例工作人员:

d["key"] = []    #Creating empty dict item
Run Code Online (Sandbox Code Playgroud)

好的,__setitem__调用,代理注意到变化。

d["key"]+=["hellostack"] #Adding first value
Run Code Online (Sandbox Code Playgroud)

这里几乎相同,首先__getitem__,不同步,然后__setitem__设置新值。

d["key"]+=[1]    #Adding second value
Run Code Online (Sandbox Code Playgroud)

与上一个相同,您先添加获取项目,然后再次设置。

d["key"][1]+=2 #<<<< ISSUE HERE - Modifying second value does nothing
Run Code Online (Sandbox Code Playgroud)

好的,__getitem__获取列表(不是 ListProxy!),然后就地修改它,列表是可变值。DictProxy 永远不会看到__setitem__呼叫并且永远不会同步任何内容。所以 worker2 永远不会看到这种变化。