【问题标题】:Making sure that all exceptions are caught in Python确保在 Python 中捕获所有异常
【发布时间】:2011-10-12 15:20:52
【问题描述】:

我用 Python 编程已经有一段时间了,但我的工作主要是创建小型实用程序脚本。我认为 Python 是一门很棒的语言,因为它很有趣,而且可以很容易地编写干净的代码。

但是,有一个烦恼我还没有找到解决方法:由于它的动态特性,可以从各种来源抛出异常,如果不被捕获它们会杀死你的程序。对我来说,这对于“大型”程序来说是一种痛苦。

在 Java 中(并不是说我对 Java 比对 Python 更了解),编译器实际上静态地强制处理异常,以便捕获所有可能的异常。是否有可能用 Python 实现相同的目标?

【问题讨论】:

标签: python exception


【解决方案1】:
try:
    # the body of your main loop or whatever
except Exception:
    # Import the traceback and system modules
    import traceback, sys
    # Prepare the arguments
    exc_type, exc_value, exc_traceback = sys.exc_info()
    # Print the exception. There are more args -- read the traceback docs!
    traceback.print_exception(exc_type, exc_value, exc_traceback)
    # This is where your house-cleaning code goes.

我使用它来确保在崩溃后保持正常状态。如果你的“优雅崩溃”代码依赖于抛出异常的任何东西......请谨慎使用它;)

【讨论】:

    【解决方案2】:

    因此,其他人已经回答了通常捕获异常的方法。我将采取稍微不同的方式。我认为您要问的是如何实现与静态类型语言相同的类型安全性。

    首先,您可能不想这样做。 python 的优势之一是duck typing。来自维基百科:

    鸭子类型是一种动态类型,其中对象的当前方法和属性集决定了有效的语义,而不是从特定类或特定接口的实现继承

    duck typing 的优点是您不必进行类型检查,您可以传递任何具有给定方法的对象。

    但是,您会遇到以下问题:“如何在不运行代码的情况下始终检查我的代码是否正确?”当错误仅作为边缘情况发生时,这尤其令人讨厌。即使在更改代码库时也能确保行为一致的一种好方法是编写unit tests。 Python 有许多不同的方法来实现单元测试。最简单的可能是doctest 模块。但是,如果您想要更强大的东西,还有unittest,以及与unittest 兼容的第三方框架nose

    单元测试的好处是您可以随时编写它们,确保寻找不常见的边缘情况,然后在您对程序进行重大更改时运行它们。然后,如果测试失败,你就知道你已经破坏了一些东西。

    【讨论】:

    • 虽然我喜欢你的回答,但我更广泛地解释了 OP 的问题。例如,确保您的程序处理 IOError(如果适用)与类型安全无关。
    【解决方案3】:

    你可能想看看sys.excepthook

    当异常被引发但未被捕获时,解释器调用 sys.excepthook 带三个参数,异常类,异常 实例和回溯对象。在交互式会话中,这 发生在控制返回到提示符之前;在 Python 中 程序这发生在程序退出之前。的处理 可以通过分配另一个来自定义此类顶级异常 sys.excepthook 的三参数函数。

    例子:

    def except_hook(type, value, tback):
        # manage unhandled exception here
        sys.__excepthook__(type, value, tback) # then call the default handler - if you need to
    
    sys.excepthook = except_hook
    

    【讨论】:

      【解决方案4】:

      好吧,您可以捕获一般异常,但这不是好的做法。

      try:
          # Execute code here
      except Exception:
          # Log error
      

      更好的方法是捕获您知道可能发生的特定异常,这样您就可以找到处理它们的特定方法。没有什么比捕获一个你不知道的异常更糟糕的了。

      【讨论】:

      • 这不会在 Python >= 2.5 中捕获 KeyboardInterrupt
      • 正如@Roman Bodnarchuk 所说,except Exception 不会捕获一些有用的异常,例如 SystemExit、KeyboardInterrupt 和 GeneratorExit,要捕获它们,请使用 pokeball(哼哼..),使用 except BaseException
      【解决方案5】:

      您可以使用简单的except: 语句捕获所有异常。但这被认为是危险的,因为这也包括语法错误。

      最佳做法是使用一个except 子句涵盖所有可能和预期的异常类型。考虑以下示例:

      except (IOError, ArgumentError), e:
          print(e)
      

      此示例捕获了两个预期异常,所有其他异常都将通过并写入stderr

      【讨论】:

      • 请注意,在 Python 3 中它是“as e”,而不是“, e”。
      • except 没有捕获 SyntaxErrors
      • 但它确实捕获了真正的错误,例如变量/成员名称拼写错误(NameErrorAttributeError),并且(如果吞下异常,OP 似乎打算这样做)会阻止调用更高级别的代码链从实际处理(而不是忽略)错误。
      • 我认为 OP 不是在询问如何捕获异常(解释器会在您的代码中断时告诉您),而是如何确保代码正确。
      • @JAB:请注意,“as e”语法在 2.7.9(可能还有 2.x 的早期版本)中也可用。从 2.7.9 教程看8.3. Handling Exceptions
      猜你喜欢
      • 2019-11-16
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-22
      • 1970-01-01
      • 2018-11-01
      • 2011-11-09
      相关资源
      最近更新 更多