Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中封装异常_Python_Python 2.7_Exception_Pip - Fatal编程技术网

在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