如何解决使用不同的类型和消息重新引发异常,保留现有信息?
引入了 (如PEP
3134中所述)。这允许在引发异常时引用现有异常作为“原因”:
try:
frobnicate()
except KeyError as exc:
raise ValueError("Bad grape") from exc
捕获的异常(exc
, 一个 KeyError )因此成为(是“原因”)新异常 ValueError 的一部分。“原因”可用于捕获新异常的任何代码。
通过使用此功能,设置__cause__
属性。内置异常处理程序还知道如何报告异常的“原因”和“上下文”以及回溯。
在 中,这个用例似乎没有很好的答案(如Ian
Bicking和Ned
Batchelder所述)。真可惜。
解决方法
我正在编写一个模块,并希望对它可以引发的异常有一个统一的异常层次结构(例如,从FooError
抽象类继承所有foo
模块的特定异常)。这允许模块的用户捕获那些特定的异常并在需要时清楚地处理它们。但是从模块中引发的许多异常都是由于其他一些异常而引发的;例如,由于文件上的
OSError 导致某些任务失败。
我需要的是 “捕获”捕获到的异常,使其具有不同的类型和消息
,以便通过捕获异常的任何方式进一步向上传播层次结构提供信息。但我不想丢失现有的类型、消息和堆栈跟踪;对于试图调试问题的人来说,这些都是有用的信息。顶级异常处理程序不好,因为我试图在异常进一步向上传播堆栈之前装饰异常,而顶级处理程序为时已晚。
这部分通过foo
从现有类型(例如class FooPermissionError(OSError,FooError)
)派生我的模块的特定异常类型来解决,但这并没有使将现有异常实例包装在新类型中变得更容易,也没有修改消息。
Python 的PEP 3134 “异常链接和嵌入式回溯”讨论了
Python 3.0 中接受的“绑定”异常对象的更改,以表明在处理现有异常期间引发了新异常。
我正在尝试做的是相关的:我需要它也可以在早期的 Python 版本中工作,而且我不需要它用于链接,而仅用于多态性。这样做的正确方法是什么?