threading ignores KeyboardInterrupt exception
我正在运行这个简单的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | import threading, time class reqthread(threading.Thread): def run(self): for i in range(0, 10): time.sleep(1) print('.') try: thread = reqthread() thread.start() except (KeyboardInterrupt, SystemExit): print(' ! Received keyboard interrupt, quitting threads. ') |
但当我运行它时,它会打印出来
1 2 3 4 5 6 7 8 9 10 11 12 | $ python prova.py . . ^C. . . . . . . . Exception KeyboardInterrupt in <module 'threading' from '/usr/lib/python2.6/threading.pyc'> ignored |
实际上,python线程忽略了我的ctrl+c键盘中断,并且不打印
尝试
1 2 3 4 5 6 7 8 9 | try: thread=reqthread() thread.daemon=True thread.start() while True: time.sleep(100) except (KeyboardInterrupt, SystemExit): print ' ! Received keyboard interrupt, quitting threads. ' |
如果不调用
当主进程结束时,
为了总结评论中建议的更改,以下内容对我很有用:
1 2 3 4 5 6 7 8 9 10 | 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 ' ! Received keyboard interrupt, quitting threads. ' sys.exit() |
稍微修改Ubuntu的解决方案。
删除tread.daemon=true,如eric建议的那样,并用signal.pause()替换休眠循环:
1 2 3 4 5 6 7 8 9 | import signal try: thread=reqthread() thread.start() signal.pause() # instead of: while True: time.sleep(100) except (KeyboardInterrupt, SystemExit): print ' ! Received keyboard interrupt, quitting threads. ' |
把
不过,请注意导入锁。我猜这就是为什么python在默认情况下不解ctrl-c的原因。
我的(hacky)解决方案是像这样使用monkey-patch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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 |