处理特定和一般的Python异常?

8
我希望能捕获特定异常并相应地处理它,然后继续执行其他异常通用的处理。从C背景下来看,我以前可以使用goto实现所需效果。目前我正在做的是这样的,它可以很好地工作:
try:
    output_var = some_magical_function()
except IntegrityError as ie:
    integrity_error_handling()
    shared_exception_handling_function(zde) # could be error reporting
except SomeOtherException as soe:
    shared_exception_handling_function(soe) # the same function as above

简而言之:

是否有“Pythonic”的方法来完成以下操作:

try:
    output_var = some_magical_function()
except IntegrityError as ie:
    integrity_error_handling()
except ALLExceptions as ae: # all exceptions INCLUDING the IntregityError
    shared_exception_handling_function(ae) # could be error reporting

NB: 我知道finally子句- 这不是为了整理(即关闭文件)。


不幸的是,在Python中,没有类似于“case switch”的技术来“穿透”某些异常,但可以构建级联的try..except结构来处理内部的特定异常,然后将其上报到外部以进行一般处理。 - woozyking
2个回答

12

您可以reraise异常,并在嵌套设置的外部处理程序中处理通用情况:

try:
    try:
        output_var = some_magical_function()
    except IntegrityError as zde:
        integrity_error_handling()
        raise
except ALLExceptions as ae: # all exceptions INCLUDING the IntregityError
    shared_exception_handling_function(ae) # could be error reporting

未经合格处理的raise语句会重新引发当前异常,因此IntegrityError异常会再次抛出以由AllExceptions处理程序处理。

另一种方法是测试异常类型:

try:
    output_var = some_magical_function()
except ALLExceptions as ae: # all exceptions INCLUDING the IntregityError
    if isinstance(ae, IntegrityError):
        integrity_error_handling()
    shared_exception_handling_function(ae) # could be error reporting

第二种方法适用于具有一组特定错误池并继承相同父异常的某些库。当泛化更难时,第一种方法更合适。在我看来,将两者结合起来几乎是防弹的,但仍然优雅/Pythonic。 - woozyking
@woozyking:但是为了让ALLExceptions捕获IntegrityError,它必须是后者的基类。 - Martijn Pieters
的确。我认为很多人会从创建继承自通用“Exception”的子类开始,然后在需要时进行中层抽象。 - woozyking
我们是否应该修改我们的问题和答案,以消除任何歧义(ALLExceptions -> Exceptions)?这将使新手在阅读线程时少一个问题... - OldTinfoil
1
我认为不应该这样做;一般来说,使用 except Exception: 或者 except: 是一个不好的想法,因为你会连同键盘中断、内存错误等一起捕获。 - Martijn Pieters

5
异常类将匹配所有异常...
try:
    output_var = some_magical_function()
except IntegrityError as zde:
    integrity_error_handling()
except Exception as ae:
    shared_exception_handling_function(ae) # could be error reporting

但是听起来你想让最终子句无论是针对IntegrityError异常还是其他所有异常都能运行。所以你需要一个不同的结构,可能是这样的:

try:
    try:
        output_var = some_magical_function()
    except IntegrityError as zde:
        integrity_error_handling()
        raise
except Exception as ae:
    shared_exception_handling_function(ae) # could be error reporting

在内部的try...except块中使用raise命令会导致捕获的异常传递到外部块。

1
“Exception” 匹配所有不导致系统退出的内置异常。 - Michael J. Barber

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