gpt4 book ai didi

python - multiprocessing.Manager().dict().setdefault() 坏了吗?

转载 作者:太空狗 更新时间:2023-10-29 20:54:39 28 4
gpt4 key购买 nike

迟到且可能很愚蠢的部门提出:

>>> import multiprocessing
>>> mgr = multiprocessing.Manager()
>>> d = mgr.dict()
>>> d.setdefault('foo', []).append({'bar': 'baz'})
>>> print d.items()
[('foo', [])] <-- Where did the dict go?

鉴于:

>>> e = mgr.dict()
>>> e['foo'] = [{'bar': 'baz'}]
>>> print e.items()
[('foo', [{'bar': 'baz'}])]

版本:

>>> sys.version
'2.7.2+ (default, Jan 20 2012, 23:05:38) \n[GCC 4.6.2]'

错误还是错误?

编辑:更多相同,在 python 3.2 上:

>>> sys.version
'3.2.2rc1 (default, Aug 14 2011, 21:09:07) \n[GCC 4.6.1]'

>>> e['foo'] = [{'bar': 'baz'}]
>>> print(e.items())
[('foo', [{'bar': 'baz'}])]

>>> id(type(e['foo']))
137341152
>>> id(type([]))
137341152

>>> e['foo'].append({'asdf': 'fdsa'})
>>> print(e.items())
[('foo', [{'bar': 'baz'}])]

dict代理中的list怎么可能不包含附加元素呢?

最佳答案

这是一些非常有趣的行为,我不太确定它是如何工作的,但我会分析为什么会出现这种行为。

首先,请注意 multiprocessing.Manager().dict() 不是 dict,它是一个 DictProxy 对象:

>>> d = multiprocessing.Manager().dict()
>>> d
<DictProxy object, typeid 'dict' at 0x7fa2bbe8ea50>

DictProxy 类的目的是为您提供一个可以安全地跨进程共享的 dict,这意味着它必须在正常的基础上实现一些锁定dict 函数。

显然,这里的部分实现是不允许您直接访问嵌套在 DictProxy 中的可变对象,因为如果允许的话,您将能够以一种方式修改您的共享对象绕过使 DictProxy 安全使用的所有锁定。

这里有一些证据表明您无法访问可变对象,这类似于 setdefault() 的情况:

>>> d['foo'] = []
>>> foo = d['foo']
>>> id(d['foo'])
140336914055536
>>> id(foo)
140336914056184

对于普通字典,您会期望 d['foo']foo 指向同一个列表对象,并且对其中一个的修改会修改另一个。如您所见,DictProxy 类不是这种情况,因为多处理模块强加了额外的进程安全要求。

编辑: 来自 multiprocessing documentation 的以下注释澄清了我上面想说的话:


Note: Modifications to mutable values or items in dict and list proxies will not be propagated through the manager, because the proxy has no way of knowing when its values or items are modified. To modify such an item, you can re-assign the modified object to the container proxy:

# 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

根据以上信息,您可以通过以下方式重写原始代码以使用 DictProxy:

# d.setdefault('foo', []).append({'bar': 'baz'})
d['foo'] = d.get('foo', []) + [{'bar': 'baz'}]

正如 Edward Loper 在评论中所建议的那样,编辑上面的代码以使用 get() 而不是 setdefault().

关于python - multiprocessing.Manager().dict().setdefault() 坏了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10807649/

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