无法使用 Ctrl-C 杀死 Python 脚本

我正在用下面的脚本测试 Python 线程:

import threading


class FirstThread (threading.Thread):
def run (self):
while True:
print 'first'


class SecondThread (threading.Thread):
def run (self):
while True:
print 'second'


FirstThread().start()
SecondThread().start()

这是在 Kubuntu 11.10上的 Python 2.7中运行的。Ctrl + C不会杀死它。我还尝试为系统信号添加一个处理程序,但这没有帮助:

import signal
import sys
def signal_handler(signal, frame):
sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)

为了终止进程,我在用 Ctrl + Z将程序发送到后台之后,通过 PID 来终止进程,这不会被忽略。为什么 Ctrl + C一直被忽略?我该怎么解决这个问题?

127886 次浏览

键盘中断和信号只能被进程(即主线程)看到... 看看 Ctrl-c 即 KeyboardInterrupt 在 python 中杀死线程

Ctrl + C终止主线程,但是由于您的线程不处于守护进程模式,因此它们继续运行,这使得进程保持活动状态。我们可以把他们变成守护神:

f = FirstThread()
f.daemon = True
f.start()
s = SecondThread()
s.daemon = True
s.start()

但是还有另一个问题——一旦主线程启动了线程,它就没有其他事情可做了。所以它退出,线程立即被破坏。因此,让我们保持主线活着:

import time
while True:
time.sleep(1)

现在它将保持打印’第一’和’第二’,直到你达到 Ctrl + C

编辑: 正如评论者所指出的,守护进程线程可能没有机会清理诸如临时文件之类的东西。如果需要,那么在主线程上捕获 KeyboardInterrupt,并让它协调清理和关闭。但在许多情况下,让守护进程线程突然死亡可能就足够了。

我认为最好在线程死亡时调用 join()。我已经擅自将您的循环改为结束(您也可以添加任何需要清理的内容)。在每次通过时检查变量 die,当它是 True时,程序退出。

import threading
import time


class MyThread (threading.Thread):
die = False
def __init__(self, name):
threading.Thread.__init__(self)
self.name = name


def run (self):
while not self.die:
time.sleep(1)
print (self.name)


def join(self):
self.die = True
super().join()


if __name__ == '__main__':
f = MyThread('first')
f.start()
s = MyThread('second')
s.start()
try:
while True:
time.sleep(2)
except KeyboardInterrupt:
f.join()
s.join()

@ Thomas K 的回答的改进版:

  • 根据 这个要点定义辅助函数 is_any_thread_alive(),自动终止 main()

示例代码:

import threading


def job1():
...


def job2():
...


def is_any_thread_alive(threads):
return True in [t.is_alive() for t in threads]


if __name__ == "__main__":
...
t1 = threading.Thread(target=job1,daemon=True)
t2 = threading.Thread(target=job2,daemon=True)
t1.start()
t2.start()


while is_any_thread_alive([t1,t2]):
time.sleep(0)

一个简单的“抓到你了”要小心,你确定 CAPS LOCK没开吗?

我在 Pi4上的 Thonny IDE 中运行 Python 脚本。打开 CAPS LOCK时,Ctrl + Shift + C被传递到键盘缓冲区,而不是 Ctrl + C