无法将项目附加到多处理共享列表

时间:2016-02-04 13:27:04

标签: python python-2.7 multiprocessing shared-memory

我使用多处理为我的应用程序创建子流程。 我还在流程和子流程之间共享字典。

我的代码示例:

主要流程:

from multiprocessing import Process, Manager
manager = Manager()
shared_dict = manager.dict()
p = Process(target=mysubprocess, args=(shared_dict,))
p.start()
p.join()
print shared_dict

我的子流程:

def mysubprocess(shared_dict):
  shared_dict['list_item'] = list()
  shared_dict['list_item'].append('test')
  print shared_dict

在这两种情况下,印刷值为: {'list_item': []}

可能是什么问题? 感谢

1 个答案:

答案 0 :(得分:7)

Manager.dict将为您提供一个直接更改将在进程之间传播的字典,但它不会检测您是否更改了dict中包含的对象(如"list_item"下存储的列表)。请参阅SyncManager documentation

底部的注释
  

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

因此,在您的示例中,当您在dict中设置列表时,列表会被同步,但附加内容不会触发另一个同步。

你可以通过在dict中重新分配密钥来解决这个问题:

from multiprocessing import Process, Manager

def mysubprocess(shared_dict):
    item = shared_dict['list_item'] = list()
    item.append('test')
    shared_dict['list_item'] = item
    print 'subprocess:', shared_dict

manager = Manager()
shared_dict = manager.dict()
p = Process(target=mysubprocess, args=(shared_dict,))
p.start()
p.join()
print 'main process:', shared_dict

但是如果列表增长很长,那可能会效率低下 - 整个列表将被序列化并发送到每个附加的管理器进程。在这种情况下,更好的方法是直接使用SyncManager.list创建共享列表(尽管如果列表的元素是可变的,您仍会遇到同样的问题 - 您需要在列表中将它们重置为在进程之间发送它们。)