关于带有字典键的多处理管理器的混淆



谁能解释为什么下面的代码会产生密钥错误?多处理器命名空间管理器的字典是否有问题?

import multiprocessing
def f(string, namespace):
    namespace.results_dict[string] = string
if __name__ == '__main__':
    mgr = multiprocessing.Manager()
    ns = mgr.Namespace()
    ns.results_dict = {}
    p = multiprocessing.Process(target=f, args=('burger', ns,))
    p.start()
    p.join()
    print(ns.results_dict)

如果在更新操作后添加打印,您将看到更新没有任何效果:

def f(string, namespace):
    namespace.results_dict[string] = string
    print(namespace)

指纹:

Namespace(results_dict={})

这是因为每次访问namespace.results_dict时,都会从托管命名空间中检索其值(空字典(。该字典的状态不受管理,仅对命名空间的直接访问是托管的。为了使您的示例正常工作,您必须使用更改的字典显式更新命名空间,例如:

def f(string, namespace):
    r = namespace.results_dict   # retrieves copy
    r[string] = string           # modify local copy
    namespace.results_dict = r   # write it back

您也可以使用托管字典作为原始函数results_dict

if __name__ == '__main__':
    mgr = multiprocessing.Manager()
    ns = mgr.Namespace()
    ns.results_dict = mgr.dict()
    p = multiprocessing.Process(target=f, args=('burger', ns,))
    p.start()
    p.join()
    print(ns.results_dict)

现在,对该字典的更改将立即可见,但对命名空间中其他可变数据结构的更改仍将仅在写入访问时更新。

不确定这是否是预期的,或者命名空间的行为是否像您期望的那样。一个简单的解决方法是从管理器对象创建dict()

import multiprocessing
def f(string, result_dict):
    result_dict[string] = string
if __name__ == '__main__':
    mgr = multiprocessing.Manager()
    ns = mgr.dict()
    p = multiprocessing.Process(target=f, args=('burger', ns,))
    p.start()
    p.join()
    print(ns)

我得到

{'burger': 'burger'}

将此Manager.dict对象分配给命名空间属性也应该有效。

最新更新