簡體   English   中英

多處理管理器在 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM