如何将应用程序与使用过的库依赖项中的异常分离?
[app] --uses--> [lib] --dependson--> [dependency]
/ /
x- <-propagates--o <---throwsexception--' /
\ /
`-----needstohandle,soimports-----> --'
问题来自真正的pip
代码:
如何在模块B中封装异常?要从模块A中删除对C的依赖?如何确保原始异常的原因和细节不会丢失?换句话说,如何用不同的名称重新引用异常?
下面的代码片段可以满足需要,但它仅适用于Python 3:
try:
dependency_call()
except DependencyError as exc:
raise LibraryError from exc
更新:我正在寻找与Python 2兼容的解决方案,Python 3添加了raise ... from ...
,这种技巧几乎可以实现。
UPDATE 2 :封装异常的目的是在[lib]
中捕获它并重新抛出一个新的[app]
来保留堆栈跟踪,以便调试工具可以仍然走上代码(对于仅限人类的解决方案the answer by Alex Thornton应该是好的)。
答案 0 :(得分:3)
您可以通过引用Exception
基类来捕获任意异常:
except Exception as exc:
raise ApplicationError from exc
要让from
成语在Python 2中运行,您将不得不破解自定义异常:
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)
然后它会在引发cause
时打印出来,如果您决定捕获ApplicationError
,也可以访问该属性。
答案 1 :(得分:0)
如果我确实让你做对了,你想更强烈地解耦并消除:
from pip._vendor import requests
和
except requests.HTTPError as exc:
你可以通过引入最后的回退处理程序来做到这一点
除了以下所有条款的最后except
:
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
缺点是,它仍然紧密耦合,明显违反了 “得墨忒耳法则”,因为你需要知道一些物体的内部结构 在对象组成中甚至都没有。所以在某种意义上说现在更糟糕了。