【问题标题】:Cannot append items to multiprocessing shared list无法将项目附加到多处理共享列表
【发布时间】:2016-05-14 03:20:26
【问题描述】:

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

我的代码示例:

主要流程:

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': []}

可能是什么问题? 谢谢

【问题讨论】:

    标签: python python-2.7 multiprocessing shared-memory


    【解决方案1】:

    Manager.dict 将为您提供一个 dict,其中将在进程之间传播直接更改,但它不会检测您是否更改了该 dict 中包含的对象(例如存储在"list_item" 下的列表)。见SyncManager documentation底部的说明:

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

    因此,在您的示例中,当您在 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 创建共享列表(尽管如果列表的元素是可变的,您仍然会遇到同样的问题 - 您需要在列表中重置它们以在进程)。

    【讨论】:

    • 我刚刚尝试过,它成功了 - 我将使用完整代码更新我的示例。
    • 您好,谢谢!现在可以了。另一个小问题......你知道我怎样才能清除所有的dict(清除shared_dict中的所有键和值)吗?
    • 为了不那么讽刺和更有帮助,您可以使用任何普通的dict方法来更改内容,这些更改将显示在其他进程中。
    • 哦,谢谢。我刚刚使用了返回 None 的 shared_dict = shared_dict.clear()...shared_dict.clear() 效果很好。
    • 不可以设个锁吗?
    猜你喜欢
    • 2021-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    相关资源
    最近更新 更多