[英]Checking for empty Queue in python's multiprocessing
我有一個使用 python 的包 multiprocessing 和 Queue 的程序。 我的功能之一具有以下結構:
from multiprocessing import Process, Queue
def foo(queue):
while True:
try:
a = queue.get(block = False)
doAndPrintStuff(a)
except:
print "the end"
break
if __name__ == "__main__"
nthreads = 4
queue = Queue.Queue()
# put stuff in the queue here
for stuff in moreStuff:
queue.put(stuff)
procs = [Process(target = foo, args = (queue,)) for i in xrange(nthreads)]
for p in procs:
p.start()
for p in procs:
p.join()
這個想法是,當我嘗試從隊列中提取並且它為空時,它會引發異常並終止循環。 所以我有兩個問題:
1)這是一個安全的習語嗎? 有沒有更好的方法來做到這一點?
2)我試圖找出當我嘗試從空隊列中.get()
時引發的確切異常是什么。 目前我的程序正在捕獲所有異常,當錯誤發生在其他地方時這很糟糕,我只收到“結束”消息。
我試過:
import Queue
queue = Queue.Queue()
[queue.put(x) for x in xrange(10)]
try:
print queue.get(block = False)
except Queue.Empty:
print "end"
break
但我收到了錯誤,就好像我沒有發現異常一樣。 捕獲的正確異常是什么?
例外應該是Queue.Empty
。 但你確定你得到了同樣的錯誤嗎? 在第二個示例中,您還將隊列本身從multiprocessing.Queue
切換到Queue.Queue
,我認為這可能是問題所在。
這可能看起來很奇怪,但您必須使用multiprocessing.Queue
類,但使用Queue.Empty
異常(您必須自己從Queue
模塊導入)
在刷新put緩沖區之前,Queue似乎是空的,這可能需要一段時間。
我們的問題的解決方案是使用 哨兵 ,也許內置task_done()調用:
task_done()
表示以前排隊的任務已完成。 由隊列使用者線程使用。 對於用於獲取任務的每個get(),對task_done()的后續調用會告知隊列該任務的處理已完成。
如果join()當前正在阻塞,則它將在所有項目都已處理后恢復(這意味着已為每個已放入隊列的項目收到task_done()調用)。
如果調用的次數超過隊列中放置的項目,則引發ValueError。
這是一個示例 - 正如@Steven 上面所說,您需要使用標准隊列中的 queue.Empty 異常。 文檔中的注釋( https://docs.python.org/3/library/multiprocessing.html ):
筆記
multiprocessing 使用通常的 queue.Empty 和 queue.Full 異常來表示超時。 它們在多處理命名空間中不可用,因此您需要從隊列中導入它們。
基本示例:
from multiprocessing import Process, Queue, Manager
import queue
def firstPass(q):
driver = getDriver()
while True:
try:
link = q.get_nowait()
f(driver, link)
except queue.Empty:
logger.info("empty queue")
driver.close()
break
嘗試閱讀隊列庫文檔。 你不是在尋找Queue.empty()嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.