线程忽略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默认情况下。