1

請看下面的例子:`apply_async`沉默「共享隊列錯誤」

from multiprocessing import Queue, Pool 

def work(*args): 
    print('work') 
    return 0 

if __name__ == '__main__': 
    queue = Queue() 
    pool = Pool(1) 
    result = pool.apply_async(work, args=(queue,)) 
    print(result.get()) 

這引發了以下RuntimeError

Traceback (most recent call last): 
    File "/tmp/test.py", line 11, in <module> 
    print(result.get()) 
    [...] 
RuntimeError: Queue objects should only be shared between processes through inheritance 

但有趣的例外才升起,當我嘗試get的結果,而不是當「分享」發生時。當我實際上確實共享隊列(並且work永遠不會執行!)時,評論相應的線路將使錯誤消失。

所以這裏去我的問題:爲什麼當請求的結果是這樣的例外,只是提出,而不是當即使錯誤似乎是公認的,因爲目標work功能從來沒有所謂的apply_async方法被調用?

看起來異常發生在不同的進程中,並且只能在進程間通信以請求結果的形式執行時纔可用於主進程。然而,然而,我想知道爲什麼在調度到另一個過程之前不執行這種檢查
(如果我用在兩個work隊列和主處理用於通信那麼這將(靜默)引入死鎖。)


Python版本是3.5.2。


我已經閱讀了以下問題:

回答

0

此行爲來自multiprocessing.Pool的設計。

在內部,當您致電apply_async時,您將您的工作放在Pool調用隊列中,然後取回一個AsyncResult對象,它允許您使用get檢索計算結果。 另一個線程然後負責酸洗你的工作。在這個線程中,發生了RuntimeError,但您已經從呼叫中返回async_apply。因此,它會將結果設置爲AsyncResult作爲例外,當您致電get時會引發該結果。

該行爲使用某種未來的結果,當您嘗試使用concurrent.futures,其中有未來明確的對象和,海事組織,更好的設計,以處理故障比較好理解,有可以查詢失敗的未來對象,而不調用get功能。

+0

謝謝你的回答!但我有個問題。如果'Queue'對象不能通過參數在進程之間共享,爲什麼我們可以通過'multiprocessing'完成這個操作。Process'對象(參見[本文檔示例 - > Queues](https://docs.python.org/3/library/multiprocessing.html#exchanging-objects-between-processes))?這不會引發'RuntimeError'並且工作正常,所以區別在哪裏?參數必須轉移到其他進程中,就像「Pool」一樣。酸洗在這裏呢? –

+0

在'Pool'中,當你實例化時,這個過程就會產生。因此,當你調用'apply_async'時,'Process'已經啓動。你可以使用'initializer'和'initargs'參數在'Pool'中傳遞'Queue'來在我認爲的子進程中聲明一個全局的'Queue'。 –

+0

您也可以將'Queue'聲明爲模塊的全局屬性,以避免混淆'initializer'。 'pickle'應該能夠處理我認爲的這種情況。 –