在Python中封装异常

2024-09-29 17:20:14 发布

您现在位置:Python中文网/ 问答频道 /正文

如何将应用程序和从已用库依赖项中潜入的异常解耦?在

[app] --uses--> [lib] --dependson--> [dependency]
                                           / /
  x- <-propagates--o <---throwsexception--' /
   \                                       /
    `-----needstohandle,soimports-----> --'

问题来自真实的pip代码:

  1. 模块A(请求/请求_集.py)depends on module B
  2. 模块B(下载)uses module C(请求)
  3. 模块A imports模块Cto handle exception from C

如何在模块B中封装异常?从模块A中删除对C的依赖?如何确保原始异常的原因和细节不丢失?换句话说,我如何用不同的名称重读异常?在

下面的代码片段执行所需的操作,但它仅限于Python 3:

^{pr2}$

更新:我正在寻找与Python2兼容的解决方案,Python3添加了raise ... from ...,这一功能几乎很好。在

更新2:封装异常的目的是在[lib]中捕获它,并重新抛出一个新的异常,以[app]保留堆栈跟踪,以便调试工具仍然可以遍历代码(对于仅限人类的解决方案the answer by Alex Thornton应该很好)。在


Tags: 模块代码fromapp应用程序lib解决方案dependency
2条回答

如果我说得对,你会更强烈地去耦合并消除:

from pip._vendor import requests

以及:

^{pr2}$

您可以通过引入最后一个备用处理程序作为 最后一个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

退一步是,这仍然是一个紧密耦合,明显违反了 “德米特定律”,因为你需要知道一个物体的内部结构 甚至不在对象组成中。所以从某种意义上说现在更糟了。在

通过引用Exception基类,可以捕获任意异常:

except Exception as exc:
    raise ApplicationError from exc

要使from习惯用法在Python 2中工作,您必须修改自定义异常:

^{pr2}$

然后像这样举起:

 except Exception, exc:
     raise ApplicationError(exc)

然后,它将在cause被引发时打印它,如果您决定捕获ApplicationError,这也是一个可以访问的属性。在

相关问题 更多 >

    热门问题