![](/img/trans.png)
[英]python 2.7 multiprocessing. pool.apply_async inside another pool.apply_async
[英]Multiprocessing Manager failing on very simple example with pool.apply_async
我在與 python multiprocessing
相關的代碼中看到了一些意外行為,尤其是與Manager
class 相關的行為。 我寫了一個超級簡單的例子來嘗試更好地理解發生了什么:
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 class 的一個非常非常簡單的應用程序。 它幾乎是官方 python 文檔中使用的實際示例的副本,唯一的區別是我使用的是池並使用 apply_async 運行進程。 我這樣做是因為這就是我在實際項目中使用的。
為了澄清,如果我沒有result =
和print(result.get())
,我不會得到堆棧跟蹤。 我只是在運行腳本時看到{'c': 2}
打印出來,這表明出現了問題並且沒有顯示出來。
有幾件事要開始:首先,這不是您運行的代碼。 您發布的代碼有
result = pool.apply_async(process2, args=(d))
但沒有定義process2()
。 假設“過程”是有意的,接下來的事情是
args=(d)
部分。 這和打字一樣
args=d
但這不是所需要的。 您需要傳遞預期 arguments 的序列。 所以你需要把那部分改成
args=(d,) # build a 1-tuple
或者
args=[d] # build a list
然后 output 更改為
{'c': 2, 'a': []}
為什么 1 和 2 不在“a”列表中? 因為只有 dict 本身存在於管理器服務器上。
d['a'].append(1)
首先從服務器獲取“a”的映射,這是一個空列表。 但是那個空列表不會以任何方式共享 - 它是本地的process()
。 你 append 1 到它,然后它就被扔掉了——服務器對此一無所知。 2也是一樣。
要得到你想要的,你需要“做點什么”告訴管理服務器你改變了什么; 例如,
d['a'] = L = []
L.append(1)
L.append(2)
d['a'] = L
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.