gpt4 book ai didi

python - 为什么 Manager().dict() 只更新了一层?

转载 作者:太空宇宙 更新时间:2023-11-04 05:15:37 26 4
gpt4 key购买 nike

我想更新 dict 中的 dict,外部的通过 multiprocessing.Manager() 实例化:

import multiprocessing

def worker(key, container):
# this one is not applied
container['a'][key] = key
# this one is
container[key] = 3

if __name__ == "__main__":
multiprocessing.freeze_support()

c = multiprocessing.Manager().dict()
c['a'] = {}

p1 = multiprocessing.Process(target=worker, args=('x',c,))
p2 = multiprocessing.Process(target=worker, args=('y',c,))

p1.start()
p2.start()
p1.join()
p2.join()
print(c.copy())

这段代码的输出是

{'y': 3, 'a': {}, 'x': 3}

我希望得到

{'y': 3, 'a': {'x': 'x', 'y': 'y'}, 'x': 3}

dict 的第一级在 worker 中是可寻址的,但是对嵌套 dict 的操作会被静默丢弃。为什么?

我最初认为这是由于浅拷贝,但使用 copy.deepcopy() 时输出是相同的

最佳答案

Manager 是使用一个子进程实现的,该子进程保留您的 dict 对象的本地版本,并提供代理函数来模拟没有 Manager< 的对象的行为.
当您调用 container['a'] 时,您使用代理函数返回与 'a' 键关联的值的本地副本。因此,如果您在您的一个子流程中修改此副本,则更改只是本地的。如果您想要全局更改,您可以:

  • 修改本地副本并使用set的代理进行同步,ie container['a'] = new_dict as你提议。不方便的是它不是原子的,因此你有一些并发问题,就好像 p1p2 获取字典一样,都获取 {},他们提交的更新只会是{key: key},不考虑其他更新,最后只会注册第二个更新。

  • 更好的方法是使用嵌套的 Manager.dict:

    import multiprocessing


    def worker(key, container):
    container['a'][key] = key
    container[key] = 3


    if __name__ == "__main__":
    multiprocessing.freeze_support()

    manager = multiprocessing.Manager()
    container = manager.dict()
    container['a'] = manager.dict()

    p1 = multiprocessing.Process(target=worker, args=('x', container))
    p2 = multiprocessing.Process(target=worker, args=('y', container))

    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print(container.copy())
    print(container['a'].copy())

关于python - 为什么 Manager().dict() 只更新了一层?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41780322/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com