[英]How do I handle exceptions when using threading and Queue?
如果我有一個使用線程和隊列的程序,如何獲取異常以停止執行? 這是一個示例程序,無法用ctrl-c停止(基本上從python文檔中刪除)。
from threading import Thread
from Queue import Queue
from time import sleep
def do_work(item):
sleep(0.5)
print "working" , item
def worker():
while True:
item = q.get()
do_work(item)
q.task_done()
q = Queue()
num_worker_threads = 10
for i in range(num_worker_threads):
t = Thread(target=worker)
# t.setDaemon(True)
t.start()
for item in range(1, 10000):
q.put(item)
q.join() # block until all tasks are done
最簡單的方法是將所有工作線程作為守護程序線程啟動,然后將主循環設為
while True:
sleep(1)
按下Ctrl + C會在您的主線程中引發異常,並且所有解釋器線程將在解釋器退出時退出。 假設您不希望在所有這些線程退出之前執行所有清理。
一種更復雜的方法是使全局事件 stopped
:
stopped = Event()
def worker():
while not stopped.is_set():
try:
item = q.get_nowait()
do_work(item)
except Empty: # import the Empty exception from the Queue module
stopped.wait(1)
然后,您的主循環可以在收到KeyboardInterrupt
時將已stopped
事件設置為False
。
try:
while not stopped.is_set():
stopped.wait(1)
except KeyboardInterrupt:
stopped.set()
這使您的工作線程可以完成您想要的工作,而不僅僅是讓每個工作線程都成為守護程序並在執行過程中退出。 您也可以執行所需的任何清理。
請注意,此示例未使用q.join()
-盡管您仍然可以使用它,但這會使事情變得更復雜。 如果這樣做,最好的選擇是使用信號處理程序而不是異常來檢測KeyboardInterrupt
。 例如:
from signal import signal, SIGINT
def stop(signum, frame):
stopped.set()
signal(SIGINT, stop)
這使您可以定義在按Ctrl + C時會發生什么,而不會影響中間的主循環。 因此,您可以繼續執行q.join()
而不必擔心被Ctrl + C中斷。 當然,在我上面的示例中,您不需要加入,但是您可能還有其他原因要加入。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.