多处理器管理器在pool.apply_async的一个非常简单的例子中失败



我在代码中看到了一些与pythonmultiprocessing相关的意外行为,尤其是Manager类。我写了一个超级简单的例子,试图更好地理解正在发生的事情:

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:
"""
Traceback (most recent call last):
File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/pool.py", line 121, in worker
result = (True, func(*args, **kwds))
File "<string>", line 2, in __iter__
File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/managers.py", line 825, in _callmethod
proxytype = self._manager._registry[token.typeid][-1]
AttributeError: 'NoneType' object has no attribute '_registry'
"""
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "mp_test.py", line 34, in <module>
main()
File "mp_test.py", line 25, in main
print(result.get())
File "/usr/local/Cellar/python/3.7.5/Frameworks/Python.framework/Versions/3.7/lib/python3.7/multiprocessing/pool.py", line 657, in get
raise self._value
AttributeError: 'NoneType' object has no attribute '_registry'

我还不清楚这里发生了什么。在我看来,这是Manager类的一个非常简单的应用程序。它几乎是官方python文档中使用的实际示例的副本,唯一的区别是我使用了一个池,并使用apply_async运行流程。我这么做是因为这是我在实际项目中使用的。

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

首先要做几件事:首先,这不是您运行的代码。你发布的代码有

result = pool.apply_async(process2, args=(d))

但没有定义CCD_ 7。假设";过程",接下来就是

args=(d)

部分。这与键入相同

args=d

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

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

args=[d]  # build a list

然后输出变为

{'c': 2, 'a': []}

为什么1和2不在"a"列表中?因为只有dict本身存在于管理器服务器上。

d['a'].append(1)

首先从服务器获取"a"的映射,该映射是一个空列表。但这个空列表并没有以任何方式共享——它是process()的本地列表。你给它加上1,然后它就被丢弃了——服务器对此一无所知。2也是如此。

为了得到你想要的,你需要;做某事;告诉管理服务器您更改了什么;例如

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

相关内容

最新更新