您需要做的是捕获中断,设置一个标志,说您已被中断,但是继续进行操作,直到需要检查该标志为止(在每个循环结束时)。由于python的try- except构造将放弃循环的当前运行,因此您需要设置适当的信号处理程序;它会处理中断,但随后让python从中断处继续执行。这是如何做:
import signal
import time # For the demo only
def signal_handler(signal, frame):
global interrupted
interrupted = True
signal.signal(signal.SIGINT, signal_handler)
interrupted = False
while True:
print("Working hard...")
time.sleep(3)
print("All done!")
if interrupted:
print("Gotta go")
break
笔记:
从命令行使用它。在IDLE控制台中,它将踩踏IDLE自己的中断处理。
更好的解决方案是在循环期间“阻止” KeyboardInterrupt,并在轮询中断时取消阻止。这是某些Unix风格的功能,但不是全部,因此python不支持它(请参阅第三个“常规规则”)
OP希望在一个类中执行此操作。但是中断函数是由信号处理系统调用的,有两个参数:信号编号和指向堆栈帧的指针-self
参数不能访问类对象。因此,设置标志的最简单方法是使用全局变量。您可以使用闭包来绑定指向本地上下文的指针(即,在中动态定义信号处理程序__init__()
,但是坦率地说,除非由于多线程或其他原因导致全局变量成为问题,否则我不会打扰。
如果您的进程处于系统调用的中间,则处理信号可能会中断系统调用。因此,这可能不适用于所有应用程序。更安全的选择是(a)在每个循环迭代的末尾使用非阻塞读取(而不是依赖信号)(并键入输入而不是^ C);(b)使用线程或进程间通信将工作人员与信号处理隔离开;或(c)如果您使用的是具有信号屏蔽功能的操作系统,请执行该操作。它们都在某种程度上依赖于操作系统,因此我将其保留下来。