Python异常处理 - 捕获除预期之外的所有异常

3

我正在使用Python编写一个简单的自动化脚本,它可能在各种位置抛出异常。在每个异常中,我想记录一个特定的消息并退出程序。为了实现这个目的,在捕获并处理异常后,我会引发SystemExit,并执行特定的日志操作等。

在主函数的顶层调用中,我做如下操作:

if __name__ == "__main__":
    try:
        main()
    except SystemExit:  # handled exception
        sys.exit(1)
    except:  # any unhandled exception
        logging.error('Unexpected error: ', exc_info=True)
        sys.exit(2)

然而,使用裸的except是不被推荐的。我是否可以使用“异常树”,在其中使用裸的except来指定“除我处理过的异常之外的所有异常”,这是一种非标准的方法吗?有更好的方法来实现这个吗?即使这些未经处理的异常没有被处理,我仍然希望记录它们。
编辑:SystemExit被触发以通知已处理异常——无论我的情况下异常是什么,我都希望停止运行脚本,因为任何失败都应该导致绝对失败。
我询问的主要原因是PEP8似乎将使用裸的except视为错误,尽管我可以使用except BaseException,但这只是语法上的区别。哪种方式更加标准,还是有其他标准方法可以实现这个目的?

顺便说一下,我认为更好的方法是停止你的代码并退出(我想这就是你在这里使用 SystemExit 的原因?),那就是定义你自己的错误并引发它。 - Stael
3个回答

2
裸露的异常会捕获你不想捕获的异常,例如GeneratorExit。请按照以下方式进行处理:
except Exception as details:
    logging.error('Unexpected error: {0}'.format(details))

这确实是一种可能的方式 - 使用BaseException而不是Exception是否更好,因为我将尝试记录任何未处理的异常? - prkist
不,使用Exception而不是BaseException的关键在于BaseException包括通常不想捕获的异常。 - BoarGules

0
使用裸的 except 的主要问题是它可以捕获像 SystemExit 和 KeyboardInterrupt 这样的非标准“代码”错误,通常不应该像处理代码生成的异常一样处理。使用 Exception 类不能覆盖这些情况,因为它们没有继承自它,所以这不仅仅是语法上的差异。

https://docs.python.org/2/howto/doanddont.html#except https://docs.python.org/3.1/howto/doanddont.html#except

如果你想处理那些特定的情况,最好像你为SystemExit所做的那样明确地处理。


1
SystemExitKeyboardInterrupt都明显继承自BaseException。请参阅异常层次结构 - Peter Wood
抱歉,我想说的是基础的“异常类”,而不是“BaseException”类。会进行更新。 - Andrew McDowell

0
这对我有用:
try:
   <code>
   raise Exception("my error")
except Exception as e:
    raise e

如果出现我的错误,将看到错误消息“my error”。 如果发生未知异常,则显示默认异常处理程序的文本。 无论哪种情况,都会引发异常并停止脚本的运行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接