python multiprocessing - 在进程之间共享类字典,随后从进程写入反映到共享内存
Posted
技术标签:
【中文标题】python multiprocessing - 在进程之间共享类字典,随后从进程写入反映到共享内存【英文标题】:python multiprocessing - Sharing a dictionary of classes between processes with subsequent writes from the process reflected to the shared memory 【发布时间】:2021-05-11 00:42:52 【问题描述】:问题
我需要在包含键值对的值组件内部的类实例的进程之间共享一个字典。使用管理器类中的多处理的 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()
【问题讨论】:
这并不是我所面临的全部问题。我也遇到过类似的问题。我认为您的代码命令每个线程都应该访问相同的内存。所以,在这种情况下,每个线程都应该在内存上等待前一个线程的进程。因为 Python 不支持autolock
函数。因此,您尝试使用 lock()
函数。尝试在 Python Official Docs about Multiprocessing 中搜索
【参考方案1】:
这是一个“陷阱”,可为外行带来很多惊喜。问题在于,当您拥有托管字典时,要查看传播的更新,您需要更改键或键的值。从技术上讲,这里您没有更改值,也就是说,您仍然引用相同的对象实例(类型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
作为变量名。
【讨论】:
以上是关于python multiprocessing - 在进程之间共享类字典,随后从进程写入反映到共享内存的主要内容,如果未能解决你的问题,请参考以下文章