【问题标题】:Python Exception in finally clause eats prior exceptionsfinally 子句中的 Python 异常会吃掉先前的异常
【发布时间】:2013-02-12 16:13:12
【问题描述】:

在我的真实案例中,Segmentation fault 出现在 finally 子句中,我对此无能为力,因为它源于通过 ctypes 使用的外部库。实际上,我并不关心这个段错误,因为脚本无论如何都完成了。

但是,finally 中的段错误会吃掉之前发生的所有异常。因此,从iDontExist 调试第一个NameError 变得很麻烦。它不会在任何地方发生。目前无法看到在段错误之前引发的任何异常。

def f1():
    try:
        while True:
            pass
    except KeyboardInterrupt:
        print iDontExist

if __name__=="__main__":
    try:
        f1()
    finally:
        raise Exception("segfault here")
        print "finally"

你觉得我能做些什么呢?修复外部库不是一种选择。

【问题讨论】:

  • 段错误不是Exception;这是一个导致操作系统终止您的程序的信号,而不是您可以在except 块中捕获的信号。如果您只想确保在写入段错误之前缓冲任何内容,您可以在可能出现段错误的行之前尝试sys.stdout.flush(); sys.stderr.flush()。如果您想在段错误之前捕获并记录异常,请在finally 之前放置一个except 块来记录它。如果你想要别的东西……你想要什么?
  • 如果我将sys.stdout.flush(); sys.stderr.flush() 放在raise Exception("segfault here") 之前,它仍然不会显示NameError。我想要什么:在finally 子句中发生任何事情之前查看引发的任何异常
  • 嗯,是的,那是因为NameError 还没有打印出来。它作为正常的 exit-interpreter-via-uncaught-exception 的一部分打印出来。如果您不以这种方式退出,则需要以其他方式将其打印出来。 (如 EOL 的示例。)
  • 不要手动刷新 stdout/stderr,而是尝试 python -u 获取无缓冲的二进制 stdout、stderr。这有什么不同吗?

标签: python exception finally try-finally try-except


【解决方案1】:

您可以尝试在 finally 之前捕获异常:

try:
    f1()
except NameError as error:  # Change as needed
    print "Error caught:", error  # Or simply "raise", in order to raise the error caught
finally:
    raise Exception("segfault here")
    print "finally"

也就是说,abamert 是对的:分段错误也不例外,因此您可能正在寻找其他东西。

【讨论】:

  • 最好显示,例如,except Exception as e:,然后打印出基于e 的代码,而不仅仅是 cmets。
  • 同时,我仍然不是 100% 清楚 OP 想要什么,但如果他只是想在 finally 中的段错误杀死他的解释器之前看到一些关于 NameError 的东西,这个正是这样做的方式。
  • @abamert:我举了一个明确的例子。
  • 是的,这可能是最好的方法。它仍然缺少行号等。不过,总比没有好。
  • @user1085954:您可以打印整个回溯,而不仅仅是打印error。详见traceback模块、exc_info函数等。我认为 EOL 只是给你一个你能做什么的样本,而不是试图为你写完整的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-12-05
  • 1970-01-01
  • 2021-09-09
  • 2011-01-31
  • 1970-01-01
相关资源
最近更新 更多