将值添加到Multiprocessing.Manager()。list()

时间:2017-02-24 18:20:37

标签: python python-3.x set multiprocessing

我正在尝试更新带有元组的集合的Manager()。list(),但无法将任何内容添加到集合中。您可以使用以下代码复制该问题:

from multiprocessing import Manager

l = Manager().list()
for _ in range(10):
    l.append(set())
l[0].add((10,10)
# returns None
l[0] = {(10,10)}
# sets l[0] to {(10,10}
l[0].add((11,11))
# returns None
l[0].add(10)
# returns None

似乎由于某种原因,无论如何,add方法都会返回None。我无法相信这是预期的行为,但也许我只是在这里遗漏了一些东西。最后,我希望能够做到的是:

l[i].add(some_tuple)

并妥善保存价值。

2 个答案:

答案 0 :(得分:2)

答案隐藏在注意部分here中(这是Python 2.7文档,但同样适用于Python 3.x):

  

注意对dict和列表代理中的可变值或项目的修改不会通过管理器传播,因为代理无法知道其值或项目何时被修改。要修改此类项,可以将修改后的对象重新分配给容器代理:

# create a list proxy and append a mutable object (a dictionary)
lproxy = manager.list()
lproxy.append({})
# now mutate the dictionary
d = lproxy[0]
d['a'] = 1
d['b'] = 2
# at this point, the changes to d are not yet synced, but by
# reassigning the dictionary, the proxy is notified of the change
lproxy[0] = d

在您的情况下,一旦您的列表代理对象l内部有set个,您就可以(在任何独立的流程中都注意到您无法在 2中执行此操作同时处理 ,因为它们也是独立的对象!)执行此操作:

x = l[0]
x.append((10, 10))
l[0] = x

或者,如果您愿意:

l[0] = l[0] | set([(10, 10)])

或者当然是新奇的Python 3集语法:

l[0] = l[0] | {(10, 10)}

注意:multiprocessing.managers.ListProxy不能(好吧, 不能,真的)直接在选定对象上实现__ior__。虽然如果您愿意,可以使用l[0] |= ...来编写这些内容:

l[0] |= ...

Python实际上将其实现为:

  1. l[index]获取值(根据需要使用锁定和/或代理),然后解锁托管对象,只返回临时对象。
  2. 对临时文件执行操作。
  3. 将结果存储到l[index](与之前一样锁定和/或代理)。
  4. 这就是为什么你必须小心不要在同一时间从两个不同的进程中修改l[0]:其中一个将首先分配,然后另一个将分配第二个,丢弃第一个 - 分配值。

答案 1 :(得分:0)

如果我不具体回答,请原谅

l.insert(索引,'无论你想添加什么(可能是元组)')

index是您要添加的地方,欢呼声