如何使用 Ctrl+C 杀死子线程?
我想在 Python 中使用 Ctrl+C 停止进程的执行。但我在某处读到,KeyboardInterrupt
异常仅在主线程中引发。我还读到,子线程执行时主线程被阻塞。那么如何杀死子线程呢?
例如,Ctrl+C 对于以下代码无效:
def main():
try:
thread = threading.Thread(target=f)
thread.start() # thread is totally blocking (e.g. while True)
thread.join()
except KeyboardInterrupt:
print "Ctrl+C pressed..."
sys.exit(1)
def f():
while True:
pass # do the actual work
I would like to stop the execution of a process with Ctrl+C in Python. But I have read somewhere that KeyboardInterrupt
exceptions are only raised in the main thread. I have also read that the main thread is blocked while the child thread executes. So how can I kill the child thread?
For instance, Ctrl+C has no effect with the following code:
def main():
try:
thread = threading.Thread(target=f)
thread.start() # thread is totally blocking (e.g. while True)
thread.join()
except KeyboardInterrupt:
print "Ctrl+C pressed..."
sys.exit(1)
def f():
while True:
pass # do the actual work
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您想让主线程在加入时接收 CTRL+C 信号,可以通过在
join()
调用中添加超时来完成。以下似乎有效(如果您希望 main 实际结束,请不要忘记添加
daemon=True
):If you want to have main thread to receive the CTRL+C signal while joining, it can be done by adding timeout to
join()
call.The following seems to be working (don't forget to add
daemon=True
if you want main to actually end):问题在于您正在使用
thread1.join()
,这将导致您的程序等待,直到该线程完成才能继续。信号总是会被主进程捕获,因为它是接收信号的进程,它是拥有线程的进程。
正如您所展示的那样,您基本上正在运行一个“正常”应用程序,没有线程功能,因为您启动 1 个线程并等待它完成才能继续。
The problem there is that you are using
thread1.join()
, which will cause your program to wait until that thread finishes to continue.The signals will always be caught by the main process, because it's the one that receives the signals, it's the process that has threads.
Doing it as you show, you are basically running a 'normal' application, without thread features, as you start 1 thread and wait until it finishes to continue.
KeyboardInterrupt
异常仅在每个进程的主线程中引发。但是Thread.join
方法会阻塞调用线程,包括KeyboardInterrupt
异常。这就是为什么 Ctrl+C 似乎没有效果。解决您的问题的一个简单方法是使方法
Thread.join
超时以解锁KeyboardInterrupt
异常,并使子线程 daemonic 让父线程在退出时杀死它(非守护子线程不会被杀死,但由其父线程在退出时加入):如果控制子线程的代码,更好的解决方案是通知子线程优雅退出(而不是像简单的解决方案那样突然退出),例如使用 threading.Event :
KeyboardInterrupt
exceptions are raised only in the main thread of each process. But the methodThread.join
blocks the calling thread, includingKeyboardInterrupt
exceptions. That is why Ctrl+C seems to have no effect.A simple solution to your problem is to make the method
Thread.join
time out to unblockKeyboardInterrupt
exceptions, and make the child thread daemonic to let the parent thread kill it at exit (non-daemonic child threads are not killed but joined by their parent at exit):A better solution if you control the code of the child thread is to notify the child thread to exit gracefully (instead of abruptly like with the simple solution), for instance using a
threading.Event
: