1

我有一个异常实例,需要根据它的类型执行代码。哪种方式更清楚 - 重新引发异常或 isinstance 检查?

重新提高:

try:
    raise exception
except OperationError as err:
    result = do_something1(err)
except (InvalidValue, InvalidContext) as err:
    result = do_something2(err)
except AnotherException as err:
    result = do_something3(err)
except:
    pass

实例检查:

if isinstance(exception, OperationError):
    result = do_something1(err)
elif isinstance(exception, (InvalidValue, InvalidContext)):
    result = do_something2(err)
elif isinstance(exception, AnotherException):
    result = do_something3(err)

PS。代码用于 django process_exception 中间件,因此在重新引发异常时,我应该except:pass为所有未知异常编写。

4

2 回答 2

1

您可以将要处理的异常作为键存储在字典中,并将不同的函数作为它们的值。然后,您可以在一个中捕获所有错误except并调用字典以确保运行相关功能。

error_handler = {
                  OperationError: do_something1,
                  InvalidValue: do_something2,
                  InvalidContext: do_something2,
                  AnotherException: do_something3,
                }

try:
    #raise your exception
except (OperationError, InvalidValue, InvalidContext, AnotherException) as err:
    result = error_handler[type(err)]()

我怀疑可能有一种方法可以以编程方式传递error_handler.keys()except,但我在 Python2.7 中尝试过的方法到目前为止还没有奏效。

请注意,正如 martineau 指出的那样,因为它type(err)用作字典键,所以它不会以那种方式处理派生的异常isinstance(err, ...)except (err)。您需要匹配确切的例外情况。

于 2015-09-04T09:17:57.953 回答
1

首先去掉这个except: pass子句——一个人永远不应该默默地传递异常,特别是在一个裸子句中(无论如何except都不应该使用一个裸子句)。except

话虽如此,“最佳”方式实际上取决于具体的用例。在您上面的示例中,您显然对不同的异常/异常集有不同的处理程序,因此显而易见的解决方案是第一个。有时您确实有一些对所有或大多数处理程序通用的代码以及一些特定于一个异常或异常子集的代码,那么您可能希望将其isinstance用于特定部分,即:

try:
   something_that_may_fail()
except (SomeException, SomeOtherException, YetAnotherOne) as e:
   do_something_anyway(e)
   if isinstance(e, YetAnotherOne):
      do_something_specific_to(e)

现在正如 mkrieger 评论的那样,要处理三个或更多异常可能是代码或设计异味——try 块中的部分可能做了太多事情——但有时你没有太多选择(调用内置函数或可能以多种不同方式失败的第三方功能...)。

于 2015-09-04T09:37:33.510 回答