我们正在使用通过引发异常(SnafuException
)来表示常见故障状态(找不到资源)的库。我们倾向于使用一种模式来处理此问题,该模式因使用情况而有所不同:
try:
foo()
except SnafuException as se:
log.exception("message", exc_info=se)
raise FubarException("message")
据我了解,log.exception不需要设置exc_info = se,但是这些消息可能会降级。
这很干净,但是我现在处于一种情况下,我希望其调用方告诉特定函数如何处理异常。
def utility(data: Data,
handler: Callable[[SnafuException], Exception] = default_handler):
try:
work_in_progress = foo(data)
except SnafuException as se:
raise handler(se)
return finish(work_in_progress)
问题出在写default_handler
;它需要返回异常,我希望返回的异常具有参数se
作为父项(上下文或原因)。鉴于工作的性质(我们是一支庞大的团队,还有其他团队可能会在与我们通常管理的相同的仓库中开展工作),我想要一个记录在某处的解决方案
return FubarException("message", cause=se)
?某些选项可能还可以,但我不满意:
handler_return_value.__cause__ = se
到处理程序中。这是documented in PEP 3134,所以很好。但是它使用的是protected / magic属性,PEP是2005年的,所以如果这是“正确”的方法,那么我希望它现在已经在其他地方有记载。try: ... except: ...
移动到处理程序函数中,这将以“动作”函数foo
作为参数。当然,这将尽可能地完全捆绑所讨论的模式,但是我担心它会混淆执行的主要流程,不够灵活,无法在许多情况下使用,并且/或者将需要大量的lambda表达式。 / li>