【问题标题】:The best way to determine exception type确定异常类型的最佳方法
【发布时间】:2015-09-04 08:57:27
【问题描述】:

我有一个异常实例,需要根据它的类型执行代码。哪种方式更清楚 - 重新引发异常或 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

【问题讨论】:

  • 你没有再加注。您正在使用特定于异常的处理程序。您认为哪个更易读且使用更少的缩进级别?
  • 另外,不要使用except: pass;你只是让MemoryErrorKeyboardInterrupt 静音。最多使用except Exception:,除非你有很好的理由(通常是再加注)。
  • 您的异常首先来自哪里?难道你不能try ... except 异常的来源而不是在变量中捕获它吗?
  • 这主要是见仁见智。根据上下文,两者都可能更清楚。当我捕获异常时,我认为在异常行中进行检查更具可读性(捕获所有然后使用 if 语句会导致更复杂、更多缩进和不太清晰的代码恕我直言)。
  • 如果你有这么多的选择来解决问题,那么有问题的代码做的太多了,IMO。

标签: python try-except isinstance


【解决方案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 块中的部分可能做了太多事情 - 但有时你又不这样做'没有太多选择(调用可能以多种不同方式失败的内置或第三方函数...)。

【讨论】:

    【解决方案2】:

    您可以将要处理的异常作为键存储在字典中,并将不同的函数作为它们的值。然后您可以在一个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) 那样处理派生异常类。您需要匹配确切的例外情况。

    【讨论】:

    • 感谢您的这个想法,但我编写函数do_something1, 2,3 只是为了举例。就我而言,可能存在随机代码块。
    • @ФархадХатамов 我认为可能是这种情况,但我仍然认为你可以考虑让函数在这里运行,因为没有太大的缺点,除非你有范围问题或必须通过各种不同的参数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-06
    • 2010-10-08
    • 2012-07-04
    相关资源
    最近更新 更多