Python的方式在捕获所有异常时执行常见操作

3
如果我有以下结构:
try:
    do_something_dangerous()
except Exception1:
    handle_exception1()
    handle_all_exceptions()
except Exception2:
    handle_exception2()
    handle_all_exceptions()
...

如果我有很多except子句,不想在每个子句中调用handle_all_exceptions,那么最Pythonic的方法是什么?也许有一种简单的方法可以在finally子句内部确定是否发生了异常?


好的,所有的答案都不错,但是没有完全解决我的问题。我希望有一种方法可以不使用 type(exc)isinstance。@nosklo 建议使用 raise 可能是最好的,但它需要两个 try 子句。 - sanyassh
@Sanyash 为什么要限制 type 或 isinstance 的使用? - Tryph
我只是在寻找一种不需要它的方法。如果没有这样的方法,我将使用它。@nosklo答案中的raise看起来很有趣,我会测试一下。 - sanyassh
@Sanyash,就像我之前所说的那样,except子句是一种类型检查,与isinstance()相同。结果也是相同的:您正在使用存储在对象的__class__中的信息来确定控制流程。 - nosklo
看起来我没有仔细阅读你之前的评论 - sanyassh
显示剩余4条评论
4个回答

4

我能想到的最简单的方法是嵌套try语句:

try:
   try:
        do_something_dangerous()
    except Exception1:
        handle_exception1()
        raise
    except Exception2:
        handle_exception2()
        raise
except Exception:
    handle_all_exceptions()

裸的raise重新抛出异常。

另一种选项是捕获所有异常并进行自己的调度,而不是使用try语句来实现:

try:
    do_something_dangerous()
except Exception as e:
    if isinstance(e, Exception1):
        handle_exception1()
    if isisntance(e, Exception2):
        handle_exception2()
    handle_all_exceptions()

2
我认为你也可以检查异常的类型。然而,我不知道这是否是最符合Python风格的方式:
编辑:查看文档,似乎没有最符合Python风格的方式。如何处理函数handle_all_exceptions()中不同类型的异常由你决定。请参见文档
try:
    do_something_dangerous()
except Exception as e:
    handle_all_exceptions(e)

def handle_all_exceptions(e):
    if isinstance(e, Exception1):
        handle_exception1()
    elif isinstance(e, Exception2):
        handle_exception2()

由于您不想检查实例或类似情况,这里提供另一种可能的实现方式。虽然列表实现绝对不是很好,但它可以解决问题而无需嵌套try语句。您也可以使用布尔语句或类似方法,但是使用列表仍然可以访问错误对象以进行进一步处理。
ex = []
try:
    do_something_dangerous()
except Exception1 as e:
    ex.append(e)
    handle_exception1()
except Exception2 as e:
    ex.append(e)
    handle_exception2()
finally:
    if ex: handle_all_exceptions(ex)

1
要同时作用于“Exception1”和“Exception2”的子类,请使用“isinstance”而不是“type(...)==”。 - user24343

1
你可以先定义一个映射,将处理函数与对应的异常关联起来:
err_handling = {
   Exception1: handle_exception1
   Exception2: handle_exception2
   # ...
}

那么你可以将抛出的异常作为handle_all_exceptions函数的参数接受,并使用处理映射和抛出异常的类型添加特定的处理。

def handle_all_exceptions(err):
    # common exception handling
    err_handling[type(err)]()

这样做可以简单地处理异常:

try:
    do_something_dangerous()
except Exception as err:
    handle_all_exceptions(err)

0

我发现了一些巧妙的解决方案,没有使用typeisinstance和大量的raise在每个except子句中。也许它不是最Pythonic的,但至少很有趣:

try:
    do_something_dangerous()
except:
    try:
        raise
    except Exception1:
        handle_exception1()
    except Exception2:
        handle_exception2()
    handle_all_exceptions()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接