线程忽略键盘中断异常
我正在运行这个简单的代码:
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')
但是当我运行它时,它会打印
$ python prova.py
.
.
^C.
.
.
.
.
.
.
.
Exception KeyboardInterrupt in <module 'threading' from '/usr/lib/python2.6/threading.pyc'> ignored
In fact python threadignore my Ctrl+C Keyboard Interrupt 并且不会打印 Received键盘中断
。为什么?这段代码有什么问题?
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+C keyboard interrupt and doesn't print Received Keyboard Interrupt
. Why? What is wrong with this code?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
Try
如果没有调用
time.sleep
,主进程会过早地跳出try... except
块,因此KeyboardInterrupt
没有被抓住。我的第一个想法是使用 thread.join,但这似乎会阻塞主进程(忽略键盘中断),直到线程完成。thread.daemon=True
导致线程在主进程结束时终止。Try
Without the call to
time.sleep
, the main process is jumping out of thetry...except
block too early, so theKeyboardInterrupt
is not caught. My first thought was to usethread.join
, but that seems to block the main process (ignoring KeyboardInterrupt) until thethread
is finished.thread.daemon=True
causes the thread to terminate when the main process ends.总结评论,以下内容对我来说效果很好:
To summarize the changes recommended in the comments, the following works well for me:
对 Ubuntu 的解决方案稍加修改。
按照 Eric 的建议删除
tread.daemon = True
并用 signal.pause() 替换睡眠循环:Slight modification of Ubuntu's solution.
Removing
tread.daemon = True
as suggested by Eric and replacing the sleeping loop by signal.pause():我的(hacky)解决方案是对
Thread.join()
进行猴子补丁,如下所示:My (hacky) solution is to monkey-patch
Thread.join()
like this:将
try ... except
放入每个线程中,并将signal.pause()
放入 truemain()
对我有用。不过请注意导入锁。我猜这就是为什么Python默认不解决ctrl-C的原因。
Putting the
try ... except
in each thread and also asignal.pause()
in truemain()
works for me.Watch out for import lock though. I am guessing this is why Python doesn't solve ctrl-C by default.
我知道这已经很老了,但我遇到了这个确切的问题,并且需要 Ctrl-C 行为才能在 Docker (ubuntu 20.04) 和 Windows 上工作。特别是在 Windows 上,仅当线程不处于等待状态时,信号处理仅在主线程上完成。对于 try: except KeyboardInterrupt: 和 signal.signal(signal.SIGINT, handler) 来说都是如此,只有当主线程退出等待时才会引发或调用。
例如,如果将代码更改为以下内容并中途按 Ctrl-C,您将看到异常被捕获,但仅当 reqThread 实际终止并因此 thread.join() 返回时。
然而,有趣的是,当主线程运行 asyncio 循环时,它总是会在 Windows 和 Linux 上捕获 Ctrl-C(至少在我运行的 docker Ubuntu 映像上)。
下面的代码演示了该行为,
并且对于我的特定应用程序,它会在 Windows 和 Ubuntu 上为您提供相同的行为
,其中需要使用 1 个运行同步代码的线程和 1 个运行异步代码的线程,我实际上总共使用了三个线程。
编辑:修复了导致第一个代码块导入语句被解释为纯文本而不是代码块的一部分的拼写错误
I know this is quite old but I had this exact issue and required the Ctrl-C behavior to work on Docker (ubuntu 20.04) and on Windows. On windows specifically, the signal handling is done only onto the main thread, only when the thread is not in a wait state. This is both true for a try: except KeyboardInterrupt: and for a signal.signal(signal.SIGINT, handler) where either gets raised or called only when the main thread is out of a wait.
For instance if you change your code to the following and press Ctrl-C midway, you will see that the exception gets caught but only when reqThread actually terminates and therefore thread.join() returns.
However, an interesting thing is that when the main thread is running an asyncio loop, it will always catch a Ctrl-C on both Windows and Linux (at least on the docker Ubuntu image I am running).
the following piece of code demonstrates the behavior
and will give you the same behavior on both Windows and Ubuntu
for my specific application where is need to use 1 thread running synchronous code and 1 thread running async code i actually use a total of three threads.
EDIT: fixed a typo that caused the first code block import statement to be interpreted as plain text instead of part of the code block