在Python中封装异常
如何将应用程序与从已用库依赖关系中潜入的异常分离在Python中封装异常,python,python-2.7,exception,pip,Python,Python 2.7,Exception,Pip,如何将应用程序与从已用库依赖关系中潜入的异常分离 [app] --uses--> [lib] --dependson--> [dependency] / / x- <-propagates--o <---throwsexception--' / \ / `-----needstohandle,s
[app] --uses--> [lib] --dependson--> [dependency]
/ /
x- <-propagates--o <---throwsexception--' /
\ /
`-----needstohandle,soimports-----> --'
更新:我正在寻找与Python 2兼容的解决方案,Python 3添加了raise。。。从…
这几乎很好地解决了问题
更新2:封装异常的目的是在
[lib]
中捕获它,并重新向[app]
抛出一个新异常,保留堆栈跟踪,以便调试工具仍然可以遍历代码(对于纯人类的解决方案应该是好的).您可以通过引用异常
基类捕获任意异常:
except Exception as exc:
raise ApplicationError from exc
要使来自的
习惯用法在Python2中工作,您必须使用自定义异常:
class ApplicationError(Exception):
def __init__(self, cause, trace):
self.cause = cause
self.trace = trace
def __str__(self):
return '{origin}\nFrom {parent}'.format(origin=self.trace,
parent=self.cause)
然后像这样举起它:
except Exception, exc:
raise ApplicationError(exc)
然后,它将在引发时打印原因
,这也是一个属性,如果您决定捕获应用程序错误
,您也可以访问该属性。如果我没有弄错,您希望更强烈地解耦并消除:
from pip._vendor import requests
以及:
您可以通过引入一个最后的应急处理程序作为
所有除外条款的最后一个除外,如:
try:...
except A:
... # here all your other exceptions
except Exception as exc: # the fall-back handler
if "HTTPError" in repr(exc):
# do whatever you want to do with the (assumed) request.HTTPError
# any other Exception with HTTPError in it's repr-string will be
# caught here
退步是,它仍然是一个紧密耦合,并且明显违反了
“得墨忒尔定律”,因为你需要知道一个物体的内部
甚至不在对象组合中。因此,从某种意义上说,现在情况更糟。虽然它提供了解耦,但我认为代码比原始代码更糟,仍然没有提供封装。此外,它还取消了静态分析或类型检查的功能。=)我不明白你的“封装”论点。在这种情况下,我不认为这是一个问题,因为自定义异常与“封装”完全相反,因为它们没有隐藏,而是通过公开额外的公共接口增加了复杂性。链由[app]-->[lib]-->[dep]
组成<代码>[lib]
应该封装所有的[dep]
异常,以对其隐藏这些额外的公共接口。异常不是要隐藏的,而是要处理的![lib]中的某些内容失败得太厉害,迫使[dep]抛出异常。“隐藏”它看起来并不理性!如果[lib]无法处理,你凭什么认为[app]可以,而不违反“德米特定律”?顺便说一句:封装是一个可怕的流行语,对当前的问题,尤其是您使用它的方式来说,它是一个误导:隐藏运行时感知到的错误行为,而不是向类型公开干净的接口。在我看来,有两种方法可以解决这个难题。第一:您可以修改[lib]并在自定义[lib]异常中包装[dep]-异常。第二:您添加了一个额外的[exclib],它为任意异常提供了一个“门面”。@techtonik来自的是可以的,您只需要定义自己的应用程序错误
异常。看起来像是Python 3的东西。对于Python 2,它给出了SyntaxError-@techtonik:Thornton先生展示其解决方案的方式看起来像是一个“包罗万象”的解决方案,但我确信他只是想尽快提供一个解决方案,并且有信心,如果不是特定的异常,您将通过重新提出异常来解决“包罗万象”。@DonQuestion,我把答案读得太快了。我不知道的实际问题是,这段代码实际上是在Python3上编译的。我更新了问题并删除了令人困惑的评论。这很酷。但它隐藏了实际错误的痕迹。Python 3显示了完整的日志(代码在这里-)
except requests.HTTPError as exc:
try:...
except A:
... # here all your other exceptions
except Exception as exc: # the fall-back handler
if "HTTPError" in repr(exc):
# do whatever you want to do with the (assumed) request.HTTPError
# any other Exception with HTTPError in it's repr-string will be
# caught here