python:异常流程:捕获后继续往下捕获块?

python: Exception flow: Continue to down catch block after catching?

我很好奇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 中处理异常的方式。当您在 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,我们抓住它,然后提出一个 TypeError 在里面抓住 AttributeError

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')

不,那不可能。内部 except 处理异常后,外部 except:

无法处理异常

来自 the docs try 语句:

When the end of this block is reached, execution continues normally after the entire try statement. (This means that if two nested handlers exist for the same exception, and the exception occurs in the try clause of the inner handler, the outer handler will not handle the exception.)

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

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

现在嵌套的 except 引发了一个异常,该异常随后被类似的处理程序捕获。

AppleError 仍然是 AppleError 而不是 BananaError,即使 error_code 不相关,所以落入 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 块。