当dict()中有set()时,.add()函数不起作用。
manager = multiprocessing.Manager()
shared_dict = manager.dict()
def worker1(d, key):
if key not in shared_dict:
d[key] = {'0': set(), '1': set()}
def worker2(d, key):
if key not in shared_dict:
d[key] = {'0': set(), '1': set()}
d[key]['0'].add(1)
d[key]['1'].add(2)
process1 = multiprocessing.Process(
target=worker1, args=[shared_dict, 'a'])
process2 = multiprocessing.Process(
target=worker2, args=[shared_dict, 'b'])
process1.start()
process2.start()
process1.join()
process2.join()
我期望以下输出:
{'a': {'1': set([]), '0': set([])}, 'b': {'1': (2), '0': (1)}}
代替:
{'a': {'1': set([]), '0': set([])}, 'b': {'1': set([]), '0': set([])}}
答案 0 :(得分:1)
您可以在Python documentation中了解有关您的问题的信息,
如果标准(非代理)列表或dict对象包含在 指代,将不会传播对那些可变值的修改 通过管理器,因为代理无法知道何时 其中包含的值将被修改。
因此,在“正常”情况下,如果您创建对对象的新引用并对其进行修改,则无论您使用哪个引用对其进行修改,修改都将应用于该对象:
a = set([1])
b = a
b.add(2)
print(a, b) # {1, 2} {1, 2}
但是,在管理器中,出于引用原因,修改不会应用于该对象。但是,您可以创建对该对象的新引用,在该位置更改值形式,然后将修改后的版本重新分配给dict。
import multiprocessing
manager = multiprocessing.Manager()
shared_dict = manager.dict()
def worker1(d, key):
d.setdefault(key, {'0': set(), '1': set()})
def worker2(d, key):
d.setdefault(key, {'0': set(), '1': set()})
buffer = d[key]
for i, (k, v) in enumerate(buffer.items()):
buffer[k].add(i)
d[key] = buffer
process1 = multiprocessing.Process(
target=worker1, args=[shared_dict, 'a'])
process2 = multiprocessing.Process(
target=worker2, args=[shared_dict, 'b'])
process1.start()
process2.start()
process1.join()
process2.join()
顺便说一句,使用dict.setdefault
重构这些if
语句。