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

Dan*_*Dan 6 python shared-memory multiprocessing python-2.7

我正在使用多处理来为我的应用程序创建子流程.我还在进程和子进程之间共享一个字典.

我的代码示例:

主要流程:

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
Run Code Online (Sandbox Code Playgroud)

我的子流程:

def mysubprocess(shared_dict):
  shared_dict['list_item'] = list()
  shared_dict['list_item'].append('test')
  print shared_dict
Run Code Online (Sandbox Code Playgroud)

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

可能是什么问题呢?谢谢

bab*_*unk 7

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

注意:对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
Run Code Online (Sandbox Code Playgroud)

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