问题
我需要在进程之间共享一个字典,该字典包含键值对的值组件内部的类实例。使用管理器类中的multiprocessing的dict()创建的字典能够存储值,但随后更新值的写入不会反映到共享内存中。
我尝试过的
为了解决这个问题,我知道我必须使用管理器从python的多处理库中创建的dict(),以便在进程之间共享。这适用于像整数和字符串这样的简单值。然而,我曾希望创建的字典能为我处理更深层次的同步,这样我就可以在字典中创建一个类,这种变化就会得到反映,但多处理似乎比这复杂得多。
示例
下面我提供了一个无法按预期工作的示例程序。打印的值不是在辅助函数f()中设置的值。
注意:我在这个例子中使用了python3
from multiprocessing import Manager
import multiprocessing as mp
import random
class ExampleClass:
def __init__(self, stringVar):
# these variables aren't saved across processes?
self.stringVar = stringVar
self.count = 0
class ProcessContainer(object):
processes = []
def __init__(self, *args, **kwargs):
manager = Manager()
self.dict = manager.dict()
def f(self, dict):
# generate a random index to add the class to
index = str(random.randint(0, 100))
# create a new class at that index
dict[index] = ExampleClass(str(random.randint(100, 200)))
# this is the problem, it doesn't share the updated variables in the dictionary between the processes <----------------------
# attempt to change the created variables
dict[index].count += 1
dict[index].stringVar = "yeAH"
# print what's inside
for x in dict.values():
print(x.count, x.stringVar)
def Run(self):
# create the processes
for str in range(3):
p = mp.Process(target=self.f, args=(self.dict,))
self.processes.append(p)
# start the processes
[proc.start() for proc in self.processes]
# wait for the processes to finish
[proc.join() for proc in self.processes]
if __name__ == '__main__':
test = ProcessContainer()
test.Run()
这是一个"明白了";这给外行带来了很多惊喜。问题是,当您有一个托管字典时,要查看传播的更新,您需要更改键或键的值。在这里,从技术上讲,您没有更改值,也就是说,您仍然在引用同一个对象实例(类型ExampleClass
),并且只是在该引用中更改。奇怪,我知道。这是您需要的修改后的方法f
:
def f(self, dict):
# generate a random index to add the class to
index = str(random.randint(0, 100))
# create a new class at that index
dict[index] = ExampleClass(str(random.randint(100, 200)))
# this is the problem, it doesn't share the updated variables in the dictionary between the processes <----------------------
# attempt to change the created variables
ec = dict[index]
ec.count += 1
ec.stringVar = "yeAH"
dict[index] = ec # show new reference
# print what's inside
for x in dict.values():
print(x.count, x.stringVar)
注意:
如果您使用以下代码来设置密钥/对值,那么以下代码实际上会打印False
:
ec = ExampleClass(str(random.randint(100, 200)))
dict[index] = ec
print(dict[index] is ec)
这就是为什么在修改后的方法f
中,dict[index] = ec # show new reference
看起来是被设置为值的新引用。
此外,您应该考虑不使用dict
(一种内置数据类型)作为变量名