Python 多处理管理器在pool.apply\u async非常简单的示例中失败

Python 多处理管理器在pool.apply\u async非常简单的示例中失败,python,python-3.x,multiprocessing,python-multiprocessing,Python,Python 3.x,Multiprocessing,Python Multiprocessing,我在我的代码中看到了一些与python多处理,尤其是管理器类相关的意外行为。我写了一个超级简单的例子,试图更好地理解发生了什么: import multiprocessing as mp from collections import defaultdict def process(d): print('doing the process') d['a'] = [] d['a'].append(1) d['a'].append(2) def main():

我在我的代码中看到了一些与python
多处理
,尤其是
管理器
类相关的意外行为。我写了一个超级简单的例子,试图更好地理解发生了什么:

import multiprocessing as mp
from collections import defaultdict


def process(d):
    print('doing the process')
    d['a'] = []
    d['a'].append(1)
    d['a'].append(2)


def main():
    pool = mp.Pool(mp.cpu_count())
    with mp.Manager() as manager:
        d = manager.dict({'c': 2})
        result = pool.apply_async(process, args=(d))
        print(result.get())

        pool.close()
        pool.join()

        print(d)


if __name__ == '__main__':
    main()
此操作失败,从
result.get()
打印的堆栈跟踪如下所示:

multiprocessing.pool.RemoteTraceback:
"""
回溯(最近一次呼叫最后一次):
文件“/usr/local/ceral/python/3.7.5/Frameworks/python.framework/Versions/3.7/lib/python3.7/multiprocessing/pool.py”,第121行,在worker中
结果=(True,func(*args,**kwds))
文件“”,第2行,在iter中__
文件“/usr/local/ceral/python/3.7.5/Frameworks/python.framework/Versions/3.7/lib/python3.7/multiprocessing/managers.py”,第825行,在调用方法中
proxytype=self.\u管理器.\u注册表[token.typeid][1]
AttributeError:“非类型”对象没有属性“\u注册表”
"""
上述异常是以下异常的直接原因:
回溯(最近一次呼叫最后一次):
文件“mp_test.py”,第34行,在
main()
文件“mp_test.py”,第25行,在main中
打印(result.get())
文件“/usr/local/ceral/python/3.7.5/Frameworks/python.framework/Versions/3.7/lib/python3.7/multiprocessing/pool.py”,get中的第657行
提升自我价值
AttributeError:“非类型”对象没有属性“\u注册表”
我还不清楚这里发生了什么。在我看来,这是一个非常非常简单的Manager类应用程序。它几乎是实际的副本,唯一的区别是我使用了一个池并使用apply\u async运行该进程。我这样做是因为这是我在实际项目中使用的


为了澄清,如果没有
result=
print(result.get())
,我就不会得到堆栈跟踪。当我运行脚本时,我只看到打印的
{'c':2}
,这向我表明出现了一些问题,没有显示出来。

首先,这不是您运行的代码。您发布的代码已被删除

  result = pool.apply_async(process2, args=(d))
但是没有定义
process2()
。假设“过程”是有意的,接下来就是

args=(d)
那和打字一样

args=d
但这不是需要的。您需要传递一系列预期参数。所以您需要将该部分更改为

args=(d,) # build a 1-tuple

然后输出更改为

{'c': 2, 'a': []}
为什么1和2不在“a”列表中?因为只有dict本身存在于manager服务器上

d['a'].append(1)
首先从服务器获取“a”的映射,该映射是一个空列表。但该空列表不会以任何方式共享-它是
process()
的本地映射。您将1附加到它,然后它被丢弃-服务器对其一无所知。对于2也是一样

要获得您想要的,您需要“做点什么”告诉manager服务器您更改了什么;例如

d['a'] = L = []
L.append(1)
L.append(2)
d['a'] = L

好的,是的,我的意思是写“进程”——这是我正在运行的代码的一个非常精简的版本,为了查看而进行了清理,而不是让我的一堆测试内容杂乱无章地散落在那里。你能详细说明一下“做点什么”吗“-不知道你写的东西是如何绕过这个问题的你的
append
调用只在列表上起作用,而列表根本不涉及dict。存储到
d[
a
]
会强制调用
d.\uuuu setitem\uuuuu
,这将委托给服务器执行。在封面下,
L
也被腌制并发送到服务器,这样服务器就可以完成
\uuuuu setitem\uuuuu
操作。我明白了。非常感谢!
d['a'] = L = []
L.append(1)
L.append(2)
d['a'] = L