【问题标题】:python: Exception flow: Continue to down catch block after catching?python:异常流:捕获后继续向下捕获块?
【发布时间】:2017-04-04 06:27:54
【问题描述】:

我很好奇python中是否有办法在try/catch块中继续,在你捕获异常后,查看它的属性,如果不相关,则继续向下堆栈。

try:
    # Code
except AppleError as apple_ex:
    # look at 'apple_ex.error_code' error body, and if not relevant, 
    # continue on to next down the catch block...
    # In other words, proceed to except BananaError and so on down.
except BananaError as banana_ex:
    # ...
except Exception as ex:
    # ...

【问题讨论】:

    标签: python exception try-catch except


    【解决方案1】:

    这不是 Python 处理异常的方式。当您在 try 块中引发异常时,如果您在 except 中处理捕获它,它将落在该块内,但不会继续到同一级别的下一个 except。观察这个功能示例:

    try:
        raise AttributeError()
    except AttributeError:
        raise TypeError()
    except TypeError:
        print("it got caught") # will not catch the TypeError raised above
    

    所以,在您的try 中,我们提出一个AttributeError,我们捕获它,然后在捕获AttributeError 内部提出一个TypeError

    except TypeError不会捕获 那个TypeError

    根据您如何解释您的问题,您需要重新考虑如何处理您的异常,看看您是否可以在其他地方确定错误的处理方式,并在那里引发错误。

    例如:

    def some_func():
        try:
            thing()
        except SomeException:
            # analyze the exception here and raise the error you *should* raise
            if apple_error_thing:
                raise AppleError
            elif banana_error_thing:
                raise BananaError
            else:
                raise UnknownException
    
    
    def your_func():
        try:
            some_func()
        except AppleError as e:
            print('Apple')
        except BananaError as e:
            print('Banana')
        except UnknownException as e:
            print('Unknown')
    

    【讨论】:

      【解决方案2】:

      即使 error_code 不相关,AppleError 仍然是 AppleError 而不是 BananaError,因此陷入 BananaError 是没有意义的。

      您可以改为为不同的错误代码定义特定的错误:

      GRANNY_SMITH_ERROR = 1
      MACINTOSH_ERROR = 2
      class AppleError(Exception): 
          def __init__(self, error_code, *args):
              super(AppleError, self).__init__(*args)
              self.error_code = error_code
      
      class GrannySmithError(AppleError):
          def __init__(self, *args):
              super(GrannySmithError, self).__init__(GRANNY_SMITH_ERROR, *args)
      
      class MacintoshError(AppleError):
          def __init__(self, *args):
              super(MacintoshError, self).__init__(MACINTOSH_ERROR, *args)
      

      那你可以尝试匹配具体的错误:

      try: raise MacintoshError()
      except MacintoshError as exc: print("mac")
      except GrannySmithError as exc: print("granny smith")
      

      如果你不关心区分不同类型的苹果错误,你仍然可以捕获所有苹果错误:

      try: raise MacintoshError()
      except AppleError as exc: print("generic apple")
      

      您可以结合这些,例如,只为 GrannySmith 做特殊处理,而不是为 Macintosh:

      try: raise MacintoshError()
      except GrannySmithError as exc: print("granny smith")
      except AppleError as exc: print("generic apple")
      

      重要的是从最具体到最不具体列出错误。如果在 GrannySmithError 之前测试 AppleError,那么它永远不会进入 GrannySmith 块。

      【讨论】:

        【解决方案3】:

        不,这是不可能的。异常被内部except处理后,它没有能力被外部except处理:

        来自the docs 上的try 声明:

        当到达该块的末尾时,在整个 try 语句之后继续正常执行。 (这意味着如果同一个异常存在两个嵌套的handler,并且异常发生在inner handler的try子句中,则outer handler不会处理该异常。)

        简而言之,您唯一的解决方案可能是在外层设置另一个处理程序,并在内部处理程序中重新raise 异常,即:

        try:
            try:
                raise ZeroDivisionError
            except ZeroDivisionError as e:
                print("caught")
                raise ZeroDivisionError
        except ZeroDivisionError as f:
            print("caught")
        

        现在嵌套的except 引发异常,因此被类似的处理程序捕获。

        【讨论】:

          猜你喜欢
          • 2020-07-01
          • 1970-01-01
          • 2011-02-07
          • 1970-01-01
          • 1970-01-01
          • 2012-02-08
          • 1970-01-01
          • 2019-10-02
          • 2010-09-28
          相关资源
          最近更新 更多