簡體   English   中英

使用線程和隊列時如何處理異常?

[英]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.

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