你现有的代码很好,但是如果你想做等价的异常链接,你可以。如果你想跳到怎么做,跳到答案末尾的第3点。
解释如何修改传播异常或执行等效的
raise Something() from existing_exception
,首先,我们必须解释异常状态如何在C级别工作。
传播异常由
per-thread
error indicator
包括
类型
,
价值
和
回溯
是的。听起来很像
sys.exc_info()
但不一样。
系统执行信息()
是为了那些
抓住了
按python级别的代码,不是仍在传播的异常。
错误指示器可能是
小精灵
,这基本上意味着构造异常对象的工作尚未执行,并且
价值
在错误指示器中不是异常的实例
类型
是的。此状态存在是为了提高效率;如果错误指示器被清除
PyErr_Clear
在需要规范化之前,Python会跳过引发异常的大部分工作。异常规范化由
PyErr_NormalizeException
,还有一些额外的工作
PyException_SetTraceback
设置异常对象的
__traceback__
属性。
皮埃尔里克
有点像C的等价物
except
块,但它只是清除了错误指示器,而不让您检查很多异常信息。要捕获异常并检查它,您需要
PyErr_Fetch
是的。
皮耶尔
就像捕捉异常和检查
系统执行信息()
,但它没有设置
系统执行信息()
或使异常正常化。它清除错误指示器并直接给出错误指示器的原始内容。
显式异常链接(
从现有的异常中引发
)通过实践来工作
PyException_SetCause
设置新异常的
__cause__
对现有的异常。这需要对两个异常都使用异常对象,因此如果要从C中执行等效操作,则必须规范化异常并调用
PyException设置原因
你自己。
隐式异常链(
raise Something()
在一个
除了
(块)通过
PyException_SetContext
设置新异常的
__context__
到现有异常。类似
PyException设置原因
这需要异常对象和异常规范化。
从现有的异常中引发
在一个
除了
块实际上设置了两个
_原因__
和
_上下文__
,如果要在C级别执行显式异常链接,通常也应该这样做。
-
就我所知,技术上是不必要的,但不管怎样,这样做可能是个好主意。看起来像
PyErr_Format
设置错误指示器的其他函数将首先清除错误指示器,如果已经设置了错误指示器,但大多数都没有记录。
-
有点,但这可能是个坏主意。可以对错误指示符进行归一化,并设置异常对象的
message
属性,但这不会影响
args
或者异常类可能对其参数做的任何其他事情,这可能会导致奇怪的问题。或者,可以使用
皮耶尔
并用一个新字符串将其还原为
PyErr_Restore
,但如果存在一个现有的异常对象,它将丢弃该对象,并对异常类的签名进行假设。
-
是的,这是可能的,但是通过公共的C API函数来做它是相当尴尬和手动的。您必须手动执行大量的规范化、反编译,并引发异常。
There
是
efforts
为了使c级异常链接更加方便,但是到目前为止,更方便的函数都被认为是内部的。例如,
_PyErr_FormatFromCause
就像
pyerr_格式
,但它将新异常与现有的传播异常(通过
_上下文__
和
_原因__
是的。
我不建议现在直接调用它;它是非常新的(3.6+),而且很可能会更改(特别是,如果看到它在新的python版本中丢失了它的前导下划线,我不会感到惊讶)。相反,复制
implementation
属于
_ Pyerr_FormatFromCause公司
/
_PyErr_FormatVFromCause
(并尊重
license
这是确保你有一个标准化和链右键的好方法。
如果要执行隐式(
_上下文__
-仅)C级异常链接-只需删除处理
_原因__
是的。