【问题标题】:What are some elegant ways to abstract out repetitive exception handling in python?有哪些优雅的方法可以抽象出 python 中的重复异常处理?
【发布时间】:2011-03-21 06:06:42
【问题描述】:

在 python 中处理异常时,我发现自己经常重复代码。基本模式是这样的:

try:
  action_here()
except CommonException1:
  Action_always_taken_for_CommonException1()
except CommonException2:
  Action_always_taken_for_CommonException2()
except Exception:
  Default_action_always_taken()

我想做的是如何将这些重复的代码抽象为一个函数或类。我知道一种方法是使用异常对象调用异常处理函数,例如:

try:
  action_here()
except Exception as e:
  handle_exception(e)

然后在这个函数中根据类判断异常。

def handle_exception(e):
  if type(e) == type(CommonException1()):
    Action_always_taken_for_CommonException1()
  elif type(e) == type(CommonException2()):
    Action_always_taken_for_CommonException2())
  else:
    Default_action_always_taken()

然而,这让人感觉笨重和不雅。所以我的问题是,处理重复异常处理还有哪些其他替代方法?

【问题讨论】:

  • 这看起来很优雅。你想用什么?
  • @Blender 我的解决方案是我想出的唯一可行的解​​决方案。我想看看是否有人知道更好的解决方案。

标签: python exception-handling


【解决方案1】:

这种情况是上下文管理器和 with 语句的主要用例之一:

from __future__ import with_statement # Needed in 2.5, but not in 2.6 or later

from contextlib import contextmanager

@contextmanager
def handle_exceptions():
    try:
        yield # Body of the with statement effectively runs here
    except CommonException1:
        Action_always_taken_for_CommonException1()
    except CommonException2:
        Action_always_taken_for_CommonException2()
    except Exception:
        Default_action_always_taken()

# Used as follows
with handle_exceptions():
    action_here()

【讨论】:

  • 这正是我正在寻找的类型。谢谢!
【解决方案2】:

如果您不喜欢重复的 if / elseif 块,您可以将句柄放在字典中,按类型键入:

handlers = { type(CommonException1()) : Action_always_taken_forCommonException1,
             type(CommonException2()) : Action_always_taken_forCommonException2 }

def handle_exception(te):
  if te in handlers:
    handlers[te]()
  else:
    Default_action()

然后你可以运行:

try:
  action_here()
except Exception as e:
  handle_exception(type(e))

另外:如果您发现自己经常编写这些 try 块,那么您可以编写自己的上下文管理器(请参阅 here)。在action_here() 一侧,您的代码将如下所示:

with my_error_handling_context():
  action_here1()
  action_here2()

在这种情况下,handle_exception 代码本质上是您的上下文管理器的 __exit__ 方法(在 with 块期间引发的任何异常都将始终传递)。

【讨论】:

  • 上下文管理器正是我正在寻找的解决方案类型。谢谢!
【解决方案3】:

虽然使用上下文管理器的解决方案(如其他人所建议的那样)是最优雅的,并且也是我所推荐的,但我想指出您的 handle_exception 函数可以通过 re 更优雅地编写-引发异常:

def handle_exception(e):
  try:
    raise e
  except CommonException1:
    Action_always_taken_for_CommonException1()
  except CommonException2:
    Action_always_taken_for_CommonException2()
  except Exception:
    Default_action_always_taken()

【讨论】:

  • 谢谢,我自己从来没想过。
猜你喜欢
  • 2015-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-05
  • 2020-01-08
  • 2010-11-22
  • 1970-01-01
  • 2014-07-29
相关资源
最近更新 更多