【问题标题】:KeyboardInterrupt not raised or caught in the case of broad Exception在广泛异常的情况下未引发或捕获 KeyboardInterrupt
【发布时间】:2014-07-17 22:04:42
【问题描述】:

有人可以向我解释以下内容吗?让我们看一下代码:

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 documentation

Python 默认安装少量信号处理程序:SIGPIPE 被忽略(因此管道和套接字上的写入错误可以报告为普通 Python 异常)并且 SIGINT 被转换为 KeyboardInterrupt 异常。所有这些都可以被覆盖。

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

【问题讨论】:

    标签: python python-2.7 signals


    【解决方案1】:

    您无法通过捕获Exception 来捕获KeyboardInterrupt,因为前者仅继承自BaseException。您可以在docs 中阅读相关内容:

    异常KeyboardInterrupt

    当用户按下中断键(通常是 Control-C 或 Delete)时触发。在执行期间,会定期检查中断。 当内置函数 input()raw_input() 是 等待输入也会引发此异常。 异常继承 来自BaseException,以免被以下代码意外捕获 捕获Exception 从而阻止解释器退出。 (强调我的)

    这意味着你必须这样做:

    except BaseException, e:
    

    但这被认为是一种不好的做法。最好像在第一个示例中那样捕获 KeyboardInterrupt 本身。

    【讨论】:

    • +1,但可能值得注意的是,捕获所有 BaseExceptions 甚至比捕获所有 Exceptions 更糟糕......
    • 这是一个单独线程的问题,但会在这里提问。如果我想对所有类型的程序终止(正常关闭)进行后处理 - 唯一的方法是为所有相应的信号添加处理程序?
    • @dizpers - 好吧,如果你想捕捉一切,那么捕捉BaseException 应该没问题。我是说如果你只是想抓住KeyboardInterrupt,那么就抓住KeyboardInterrupt。 :)
    • 如果你想抓住一切,就用裸except:
    • @kindall - 或者那个。 :) 至少列出 something 对我来说是一种习惯力量。
    猜你喜欢
    • 2022-08-03
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    • 2011-08-25
    • 2014-04-12
    • 1970-01-01
    • 2013-02-18
    • 2019-11-04
    相关资源
    最近更新 更多