簡體   English   中英

Python 2.6 multiprocessing.Queue與線程兼容?

[英]Python 2.6 multiprocessing.Queue compatible with threads?

我正在使用Python 2.6中的新多處理模塊進行實驗。 我正在創建幾個進程,每個進程都有自己的multiprocessor.JoinableQueue實例。 每個進程生成一個或多個工作線程(threading.Thread的子類),它們共享JoinableQueue實例(通過每個Thread的__init__方法傳入)。 它似乎通常工作,但偶爾和不可預測的失敗,出現以下錯誤:

  File "C:\Documents and Settings\Brian\Desktop\testscript.py", line 49, in run
    self.queue.task_done()
  File "C:\Python26\lib\multiprocessing\queues.py", line 293, in task_done
    raise ValueError('task_done() called too many times')
ValueError: task_done() called too many times

我的隊列get()和task_done()調用是在彼此之后,因此它們應該是相等的。 有趣的是,這似乎只有在get()和task_done()之間完成的工作非常快時才會發生。 插入一個小的time.sleep(0.01)似乎可以緩解這個問題。

有什么想法發生了什么? 我可以使用帶有線程的多處理器隊列而不是更傳統的(Queue.Queue)嗎?

謝謝!

布賴恩

我還沒有在2.6中嘗試過多處理,但我在pyprocessing中玩了很多(因為它在2.5中被稱為)。

我可以看到你正在尋找許多進程,每個進程分別生成一組線程。

由於您正在使用多處理模塊,我建議使用多進程而不是多線程方法,您將遇到更少的問題,如死鎖等。

創建一個隊列對象。 http://pyprocessing.berlios.de/doc/queue-objects.html

要創建多進程環境,請使用池: http//pyprocessing.berlios.de/doc/pool-objects.html ,它將為您管理工作進程。 然后,您可以將異步/同步應用於worker,並且還可以根據需要為每個worker添加回調。 但請記住回調是一個公共代碼塊,它應該立即返回(如文檔中所述)

一些額外的信息:如果需要,創建一個管理器http://pyprocessing.berlios.de/doc/manager-objects.html來管理對隊列對象的訪問。 您必須為此共享隊列對象。 但優點是,一旦共享和管理,您就可以通過創建代理對象來訪問整個網絡中的此共享隊列。 這將使您能夠將集中式共享隊列對象的方法作為(顯然)任何網絡節點上的本機方法。

這是文檔中的代碼示例

可以在一台計算機上運行管理服務器,並讓客戶端從其他計算機上使用它(假設所涉及的防火牆允許它)。 運行以下命令會為遠程客戶端可以使用的共享隊列創建服務器:

>>> from processing.managers import BaseManager, CreatorMethod
>>> import Queue
>>> queue = Queue.Queue()
>>> class QueueManager(BaseManager):
...     get_proxy = CreatorMethod(callable=lambda:queue, typeid='get_proxy')
...
>>> m = QueueManager(address=('foo.bar.org', 50000), authkey='none')
>>> m.serve_forever()

一個客戶端可以按如下方式訪問服務器:

>>> from processing.managers import BaseManager, CreatorMethod
>>> class QueueManager(BaseManager):
...     get_proxy = CreatorMethod(typeid='get_proxy')
...
>>> m = QueueManager.from_address(address=('foo.bar.org', 50000), authkey='none')
>>> queue = m.get_proxy()
>>> queue.put('hello')

如果您堅持使用安全的線程,PEP371(多處理)會引用此http://code.google.com/p/python-safethread/

您應該將Queue對象作為目標參數傳遞。

多處理文檔中的示例:

from multiprocessing import Process, Queue

def f(q):
    q.put([42, None, 'hello'])

 if __name__ == '__main__':
     q = Queue()
     p = Process(target=f, args=(q,))
     p.start()
     print q.get()    # prints "[42, None, 'hello']"
     p.join()

隊列是線程和進程安全的。

您可能遇到此錯誤:

http://bugs.python.org/issue4660

感謝您及時的回復。 我正在將multiprocessing.Queue實例作為參數傳遞給每個進程,如圖所示。 失敗似乎發生在線程中。 我通過子類化threading.Thread並將隊列傳遞給每個線程實例的' init '方法來創建它們。 這似乎是將隊列傳遞給線程子類的可接受方式。 我唯一認為多處理隊列可能與線程不兼容(盡管它們應該是線程安全的)。

暫無
暫無

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

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