Python 线程忽略键盘中断异常
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3788208/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
threading ignores KeyboardInterrupt exception
提问by Emilio
I'm running this simple code:
我正在运行这个简单的代码:
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('\n! Received keyboard interrupt, quitting threads.\n')
But when I run it, it prints
但是当我运行它时,它会打印
$ python prova.py
.
.
^C.
.
.
.
.
.
.
.
Exception KeyboardInterrupt in <module 'threading' from '/usr/lib/python2.6/threading.pyc'> ignored
In fact python thread ignore my Ctrl+Ckeyboard interrupt and doesn't print Received Keyboard Interrupt. Why? What is wrong with this code?
实际上python线程忽略我的Ctrl+C键盘中断并且不打印Received Keyboard Interrupt。为什么?这段代码有什么问题?
采纳答案by unutbu
Try
尝试
try:
thread=reqthread()
thread.daemon=True
thread.start()
while True: time.sleep(100)
except (KeyboardInterrupt, SystemExit):
print '\n! Received keyboard interrupt, quitting threads.\n'
Without the call to time.sleep, the main process is jumping out of the try...exceptblock too early, so the KeyboardInterruptis not caught. My first thought was to use thread.join, but that seems to block the main process (ignoring KeyboardInterrupt) until the threadis finished.
如果没有调用time.sleep,主进程会try...except过早地跳出块,因此KeyboardInterrupt不会被捕获。我的第一个想法是使用thread.join,但这似乎会阻止主进程(忽略 KeyboardInterrupt)直到thread完成。
thread.daemon=Truecauses the thread to terminate when the main process ends.
thread.daemon=True导致线程在主进程结束时终止。
回答by rattray
To summarize the changes recommended in thecomments, the following works well for me:
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()
回答by Albert
My (hacky) solution is to monkey-patch Thread.join()like this:
我的(hacky)解决方案是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
回答by yaccob
Slight modification of ubuntu's solution.
对 ubuntu 的解决方案稍作修改。
Removing tread.daemon = True as suggested by Eric and replacing the sleeping loop by signal.pause():
按照埃里克的建议删除tread.daemon = True 并通过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'
回答by personal_cloud
Putting the try ... exceptin each thread and also a signal.pause()in truemain()works for me.
把try ... except每个线程,也是一个signal.pause()在真正main()为我工作。
Watch out for import lockthough. I am guessing this is why Python doesn't solve ctrl-C by default.
不过要注意导入锁。我猜这就是 Python 默认不解决 ctrl-C 的原因。

