【问题标题】:How to catch a custom exception not defined by me in python如何在python中捕获我未定义的自定义异常
【发布时间】:2021-07-05 23:15:35
【问题描述】:

我有以下 try 块:

try:
   # depending on conditions, this can generate several types of errors
   mymodule.do_stuff()
except Exception as e:
   print("something went wrong, the error was :" + type(e).__name__)

我想捕捉来自do_stuff() 的潜在错误。经过反复试验,我能够通过打印 type(e).__name__ 值来生成可能由 do_stuff() 触发的潜在错误列表:

DoStuffInsufficientMemoryException
DoStuffInsufficientCPUException
DoStuffInsufficientDiskException

但如果我尝试将我的 except 语句从 except Exception as e 修改为 except DoStuffInsufficientMemoryException,我将收到 DoStuffInsufficientMemoryException 未定义的错误。

我尝试定义一个扩展 Exception 的类,正如这里的大多数教程/问题所建议的那样,基本上:

class WAFInvalidParameterException(Exception):
    pass

所以现在该变量已被识别,但由于我无法控制do_sutff() 将引发的错误,所以我不能在我的初始尝试块中真正raise 这个异常。

理想情况下,我希望每个错误都有 1 个 except 块,所以我希望有类似的内容:

try:
   mymodule.do_stuff()
except DoStuffInsufficientMemoryException:
    free_memory()
except DoStuffInsufficientCPUException:
    kill_processes()
except DoStuffInsufficientDiskException:
    free_disk_space()

但这当然行不通,因为这些变量没有定义。

【问题讨论】:

    标签: python python-3.x exception error-handling


    【解决方案1】:

    就像您不能在没有模块说明符的情况下引用 do_stuff 一样,您必须指定在哪个模块命名空间中定义了这些异常。

    try:
        mymodule.do_stuff()
    except mymodule.DoStuffInsufficientMemoryException:
        free_memory()
    except mymodule.DoStuffInsufficientCPUException:
        kill_processes()
    except mymodule.DoStuffInsufficientDiskException:
        free_disk_space()
    

    如果free_memory 也在mymodule 命名空间中,当然你也需要在那里指定它。

    或者,当您导入mymodule 时,您可以将选定的符号显式导入当前命名空间:

    from mymodule import do_stuff, DoStuffInsufficientMemoryException, ...
    

    然后,因为它们在当前包中,您可以(或确实必须)在没有包前缀 mymodule. 的情况下引用它们

    一个设计良好的模块会导出选定的符号,这样您就可以在没有包前缀的情况下引用它们,但这对您自己的包是否有意义取决于它的总体设计和目标受众。一些大包为异常定义了一个单独的子包,所以你可以说

    import bigpackage.exceptions
    

    全部导入。您可能仍想探索包的文档(或者,如果缺少它的源代码)以发现存在哪些异常以及它们是如何组织的。许多包定义了一个基异常类,它的所有其他异常都是子类,这样您就可以轻松地用一个符号捕获它们,例如

    try:
        bigpackage.heavy_wizardry()
    except bigpackage.BigBaseException:
        print("you are turned into a frog")
    

    【讨论】:

      【解决方案2】:

      编辑:当然,您可以导入其他方法而不是创建自己的方法

      try/except 块将尝试执行代码,如果出现错误引发并在 except 语句中指定,它将停止执行位于 try 块中的代码并执行位于 except 块中的其他代码。因此,要捕获您的自定义错误,您必须首先提出它。

      如果您不知道,可以使用 raise 语句引发错误。在这里,我编写了一段简单的代码。我有一个自定义错误,一个初始化为 2 的变量 x,以及一个将 1 添加到参数中给出的变量的方法。如果变量变为 3,该方法将引发 CustomError。

      # Here, I define the custom error and allow a custom message to be displayed
      # using the super() method
      
      class CustomError(Exception):
          def __init__(self, msg):
              super().__init__(msg)
      
      
      # I initialize x at 2
      x = 2
      
      
      # I create the method that will add 1 to the variable given in argument
      # and raise a CustomError if the variable becomes 3
      # This is completely random, and you can make whatever checks you want before raising
      # Your custom error
      def do_stuff(x):
          x += 1
          if x == 3:
              raise CustomError("x is 3")
      
      
      # Now, I write the try/except block. I raise e (the CustomError) if it is
      # being raised in the method do_stuff(x)
      try:
          do_stuff(x)
      except CustomError as e:
          raise e
      

      请随意尝试代码以更好地理解它!

      【讨论】:

        【解决方案3】:

        通常是一个函数

        module.foo()
        

        抛出异常 DoStuffInsufficientMemoryException 它也可以导入为

        from module import DoStuffInsufficientMemoryException
        

        如果这导致ImportError,那么您需要此答案中的fullname 函数;与e 一起使用(它接受一个实例并返回类名)。如果它给了

        foo.bar.DoStuffInsufficientMemoryException
        

        然后您可以将异常导入为

        from foo.bar import DoStuffInsufficientMemoryException
        

        以上内容可能不适用于所有情况。一个值得注意的案例是 Boto 3 AWS 客户端库,它使异常可导入 - 而是 they will be attributes on the client instance

        【讨论】:

        • 这不是__qualname__ 所做的——它适用于嵌套在其他类或函数中的类和函数。 (最常见的情况是方法。)对于模块名称,您需要__module__
        • @user2357112supportsMonica 需要更多咖啡。固定
        猜你喜欢
        • 2017-05-24
        • 1970-01-01
        • 2018-01-25
        • 1970-01-01
        • 2015-06-07
        • 1970-01-01
        • 1970-01-01
        • 2012-02-03
        • 2013-06-19
        相关资源
        最近更新 更多