线程忽略KeyboardInterruptexception

我正在运行这个简单的代码:

import threading, time class reqthread ( threading.Thread ): def __init__ (self): threading.Thread.__init__(self) def run ( self ): for i in range(0,10): time.sleep(1) print '.' try: thread=reqthread() thread.start() except (KeyboardInterrupt, SystemExit): print '\n! Received keyboard interrupt, quitting threads.\n' 

但是当我运行它,打印

 $ python prova.py ` . . ^C. . . . . . . . Exception KeyboardInterrupt in <module 'threading' from '/usr/lib/python2.6/threading.pyc'> ignored ` 

其实python线程忽略我的Ctrl + C键盘中断,并不打印Received Keyboard Interrupt 。 为什么? 这段代码有什么问题?

尝试

 try: thread=reqthread() thread.daemon=True thread.start() while True: time.sleep(100) except (KeyboardInterrupt, SystemExit): print '\n! Received keyboard interrupt, quitting threads.\n' 

如果没有调用time.sleep ,主进程就会跳出try...except块,所以KeyboardInterrupt不会被捕获。 我的第一个想法是使用thread.join ,但似乎阻止主进程(忽略KeyboardInterrupt),直到thread完成。

thread.daemon=True会导致主进程结束时线程终止。

总结评论中推荐的更改,以下内容适用于我:

 try: thread = reqthread() thread.start() while thread.isAlive(): thread.join(1) # not sure if there is an appreciable cost to this. except (KeyboardInterrupt, SystemExit): print '\n! Received keyboard interrupt, quitting threads.\n' sys.exit() 

Ubuntu的解决scheme略有修改。

删除tread.daemon =真正的build议由埃里克和更换hibernate循环signal.pause():

 import signal try: thread=reqthread() thread.start() signal.pause() # instead of: while True: time.sleep(100) except (KeyboardInterrupt, SystemExit): print '\n! Received keyboard interrupt, quitting threads.\n' 

我的(哈克)解决scheme是像这样猴子修补Thread.join()

 def initThreadJoinHack(): import threading, thread mainThread = threading.currentThread() assert isinstance(mainThread, threading._MainThread) mainThreadId = thread.get_ident() join_orig = threading.Thread.join def join_hacked(threadObj, timeout=None): """ :type threadObj: threading.Thread :type timeout: float|None """ if timeout is None and thread.get_ident() == mainThreadId: # This is a HACK for Thread.join() if we are in the main thread. # In that case, a Thread.join(timeout=None) would hang and even not respond to signals # because signals will get delivered to other threads and Python would forward # them for delayed handling to the main thread which hangs. # See CPython signalmodule.c. # Currently the best solution I can think of: while threadObj.isAlive(): join_orig(threadObj, timeout=0.1) else: # In all other cases, we can use the original. join_orig(threadObj, timeout=timeout) threading.Thread.join = join_hacked 

try ... except每个线程,还有一个signal.pause()真正的 main()为我工作。

小心inputlocking 。 我猜这就是为什么Python不解决ctrl-C默认情况下。