簡體   English   中英

如何在功能中使用多重處理?

[英]How to use multiprocessing in function?

我想在“ a.py”中定義一個函數,該函數使用多處理進行並行化,然后將其作為庫函數導入“ b.py”中。 例如,在“ a.py”中:

import multiprocessing as mp, queue

def MPWorker(input, i):
    input.put(i)


def MPTest(MaxMPNum):
    jobs = []
    BatchResult = queue.Queue()
    for i in range(MaxMPNum):
        p = mp.Process(target=MPWorker, args=(BatchResult, i + 1))
        p.start()
        print("this is", i)
        jobs.append(p)
    for i in range(MaxMPNum):
        print("getting", i)
        result = BatchResult.get()
        print(result)

然后在“ b.py”中:

import a
a.MPTest(10)

但是,它將無法正常工作,我將始終收到錯誤:_pickle.PicklingError:無法進行腌制:_thread上的屬性查找鎖定失敗。 那么,是否有可能以這種方式使用python的多處理功能,或者我錯過了任何東西?

整個追溯,略做編輯(Python 3.x,Windows):

Traceback (most recent call last):
  File "F:/b.py", line 72, in <module>
    a.MPTest(5)
  File "F:\a.py", line 566, in MPTest
    p.start()
  File "C:\Python34\lib\multiprocessing\process.py", line 105, in start
    self._popen = self._Popen(self)
  File "C:\Python34\lib\multiprocessing\context.py", line 212, in _Popen
    return _default_context.get_context().Process._Popen(process_obj)
  File "C:\Python34\lib\multiprocessing\context.py", line 313, in _Popen
    return Popen(process_obj)
  File "C:\Python34\lib\multiprocessing\popen_spawn_win32.py", line 66, in __init__
    reduction.dump(process_obj, to_child)
  File "C:\Python34\lib\multiprocessing\reduction.py", line 59, in dump
    ForkingPickler(file, protocol).dump(obj)
_pickle.PicklingError: Can't pickle <class '_thread.lock'>: attribute lookup lock on _thread failed

問題在於您使用的是queue.Queue ,它僅在同一進程中的線程之間起作用,而不是multiprocessing.Queue ,其在進程之間是起作用的。

根據您的平台和使用方式,這將以不同的方式失敗。 在您的情況下,因為您正在嘗試將隊列作為參數傳遞給Process構造函數,並且您在Windows上,則會遇到最棒的錯誤:嘗試對隊列本身進行酸洗,然后失敗。*在Unix上,您實際上可以成功地將隊列傳遞給子進程,但是當您使用它時,它可能會丟失大多數值(OS X)或死鎖(大多數其他系統)。

正如文檔所解釋的, multiprocessing.Queue “是queue.Queue的近乎克隆”,除了它是“線程和進程安全的”,而不僅僅是線程安全的。


如果您認為您正在使用multiprocessing.Queue ,那么您的錯誤就在此行中:

import multiprocessing as mp, queue

這不會同時將multiprocessing作為mpqueue導入,而是將multiprocessing作為mp導入,並將queue本身作為導入。 有關詳細信息,請參見import參考。

它對人類是不明確的(即使它對解析器而言不是不明確的事實)是在Python中不鼓勵多次導入語句的原因之一。 例如, PEP 8說“導入通常應該放在單獨的行上”。


*如果在您對其進行腌制時隊列本身引發了異常,而不是依賴於它使用一些不可腌制的線程同步對象這一事實可能會更好,因為對_thread.lock進行腌制並不是完全由腌制queue.Queue引起的queue.Queue

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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