Joa*_*org 10 python multithreading exception
如果我有一个使用线程和队列的程序,我如何获得停止执行的异常?这是一个示例程序,不能用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
Run Code Online (Sandbox Code Playgroud)
最简单的方法是将所有工作线程作为守护程序线程启动,然后将主循环设置为
while True:
sleep(1)
Run Code Online (Sandbox Code Playgroud)
按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)
Run Code Online (Sandbox Code Playgroud)
然后你的主循环可以将stopped事件设置为何False时获得KeyboardInterrupt
try:
while not stopped.is_set():
stopped.wait(1)
except KeyboardInterrupt:
stopped.set()
Run Code Online (Sandbox Code Playgroud)
这使您的工作线程可以完成他们想要的操作,而不是让每个工作线程都成为守护进程并在执行过程中退出.你也可以做任何你需要的清理工作.
请注意,此示例未使用q.join()- 这会使事情变得更复杂,尽管您仍然可以使用它.如果你这样做,那么最好的办法是使用信号处理程序而不是异常来检测KeyboardInterrupts.例如:
from signal import signal, SIGINT
def stop(signum, frame):
stopped.set()
signal(SIGINT, stop)
Run Code Online (Sandbox Code Playgroud)
这使您可以定义在按Ctrl + C时发生的情况,而不会影响主循环的中间位置.所以你可以继续做q.join()而不用担心被Ctrl + C打断.当然,在上面的示例中,您不需要加入,但您可能还有其他原因要这样做.
| 归档时间: |
|
| 查看次数: |
5553 次 |
| 最近记录: |