python 中的多个异常处理程序

multiple exception handler in python

我正在编写必须处理大量 IndexError 异常的代码。
所以,我使用了 try except 块:

try:
    <do some level_1 calculations>
except IndexError:
    <change to level_2 calculations>  

但是,如果我的异常处理程序再次引发另一个 IndexError 怎么办?
我怎样才能安全地将另一个 IndexError 异常放入此代码结构中,这样,如果 level_2 计算再次陷入 IndexError,那么代码将作为异常运行 "level_3 calculations"等等。

您可以只嵌套 try except 个块,如下所示:

try:
    <do some level_1 calculations>
except IndexError:
    try:
        <change to level_2 calculations>
    except IndexError:
        try:
            <change to level_3 calculations>
        except IndexError:
            <change to level_4 calculations>

但这看起来很乱,如果你弄乱了格式,可能会造成麻烦,最好使用一个函数列表,你可以循环尝试不同的计算,直到所有的都失败,然后你用其他方式处理异常方式。

calulators = [
                 level_1_calculation_function,
                 level_2_calculation_function,
                 level_3_calculation_function,
             ]

for attempt in range(len(calculators)):
    try:
        result = calculators[attempt]
        break #If we've reached here, the calculation was successful
    except IndexError:
        attempt += 1
else:
    #If none of the functions worked and broke out of the loop, we execute this.
    <handle_exception>

一般来说,当您编写代码时,您应该了解在任何阶段可能发生的事情,并且您应该相应地放置您的异常处理程序。

也就是说,如果您正在执行一系列操作,其中有多个地方可能导致特定异常,您可以将整个块封装到一个适当类型的异常处理程序中。在其他情况下,当您由于某些其他异常而需要不同的行为时,请定义单独的处理程序。

这两种方式在逻辑上都是正确的,而是设计问题。

将 calculations/funcs 放入列表中:

from random import choice
from operator import mul, add

funcs = [mul, add]

for f in funcs:
    try:
        i = l[choice([1, 2, 3])]
        calc = f(i[0], i[1])
        print(calc)
        break # break if you want the first successful calc to be the last
    except IndexError as e:
        print(e)
        continue

如果您 运行 代码,您将看到随机索引错误被捕获。

嵌套 try-except 块是正确的方法。因为可能的异常发生在您的 try 块 外部 之外。

还有另一种方法,但这不是如果您没有非常具体的理由使用它,我会建议您。它使事情看起来有点混乱,并要求您使用彼此嵌套的默认 try-except 块和最终的 try-except 块来覆盖它们!

class FirstLevelFuncException(Exception):
    pass

class SecondLevelFuncException(Exception):
    pass

class ThirdLevelFuncException(Exception):
    pass

try: 
# This is the base try block that will cover your code and catch Function Level based exceptions
    try:
        <do some level_1 calculations>
    except IndexError:
        try:
            <change to level_2 calculations>
        except IndexError:
            try:
                <change to level_3 calculations>
            except IndexError:
                <change to level_4 calculations>
            else:
                raise SecondLevelFuncException()
        else:
            raise FirstLevelFuncException()
    else:
        pass
except Exception as e:
    print e

它将尝试按给定顺序执行函数,当它无误地完成一个步骤时,它会引发与上一级相关的异常,因此您可以跟踪执行情况。

但正如我所说,除非您有非常特殊的需求,否则这不是一个好的和正确的方法