Python多重处理:dict()中的set()不起作用

时间:2019-08-26 05:49:17

标签: python-3.x set multiprocessing

当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([])}}

1 个答案:

答案 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语句。