在广泛异常情况下未引发或捕获KeyboardInterrupt

4 投票
1 回答
2713 浏览
提问于 2025-04-18 07:50

有人能给我解释一下以下内容吗?我们先来看这段代码:

if __name__ == '__main__':
    try:
        while 1:
            x = 2+2
    except KeyboardInterrupt:
        print('yo')

如果我运行这个代码,等一会儿,然后按下 Ctrl+C,就会处理一个异常,并且会打印出消息 yo

如果我们把代码改成捕获更广泛的异常,像这样:

if __name__ == '__main__':
    try:
        while 1:
            x = 2+2
    except Exception, e:
        print('yo')
        print(e)

运行它,等一会儿,再按 Ctrl+C,这个 KeyboardInterrupt 异常就不会被捕获。

根据 Python 的文档

Python 默认安装了一小部分信号处理程序:SIGPIPE 会被忽略(这样在管道和套接字上的写入错误可以作为普通的 Python 异常报告),而 SIGINT 会被转换成 KeyboardInterrupt 异常。所有这些都可以被覆盖。

那么,为什么在第二种情况下,这个异常没有被捕获,甚至没有被抛出呢?

1 个回答

5

你不能通过捕获 Exception 来处理 KeyboardInterrupt,因为前者只继承自 BaseException。你可以在 文档中了解更多信息:

异常 KeyboardInterrupt

当用户按下中断键(通常是 Control-C 或 Delete)时会引发这个异常。在程序运行时,会定期检查是否有中断信号。如果在内置函数 input()raw_input() 等待输入时输入了中断信号,也会引发这个异常。这个异常是从 BaseException 继承的,这样就不会被捕获 Exception 的代码意外捕获,从而防止解释器无法正常退出。(强调是我的)

这意味着你需要这样做:

except BaseException, e:

但这被认为是一种不好的做法。更好的方法是直接捕获 KeyboardInterrupt,就像你第一个例子中那样。

撰写回答