问题描述
我有一些 cython 类,在它们的 cdef
方法中,我有 assert
语句。但是,例如,我没有得到我可以捕捉到的 AssertionError
,而是得到了 Exception ignored in:
并且我无法捕捉到它(pytest
也将此报告为警告)
此外,不会引发和忽略发生的其他错误(除了 assert
错误)。
cdef class Node:
def __init__(self,ident):
self.identifier = ident
self.children = set()
self.parents = set()
cdef void add_child(self,Node child):
self.children.add(child.identifier)
child.parents.add(self.identifier)
cdef void add_parent(self,Node parent):
self.parent.add(parent.identifier)
parent.children.add(self.identifier)
cdef void remove_child(self,Node child):
assert child.identifier in self.children
self.children.remove(child.identifier)
child.parents.remove(self.identifier)
cdef void remove_parent(self,Node parent):
assert parent.identifier in self.parents
self.parents.remove(parent.identifier)
parent.children.remove(self.identifier)
及其相应的 Node.pxd
文件
cdef class Node:
cdef int identifier
cdef set children
cdef set parents
cdef void add_child(self,Node child)
cdef void add_parent(self,Node parent)
cdef void remove_child(self,Node child)
cdef void remove_parent(self,Node parent)
因为这都是 cdef
,所以它只能被另一个 pyx
脚本或函数使用。因此,让我们使用另一个脚本来测试节点,node_test.pyx
from Node cimport Node
def test_error_raising():
cdef Node node1 = Node(1)
cdef Node node2 = Node(2)
node1.remove_parent(node2)
现在,如果我用 cythonize -i *pyx
或 simpel 安装脚本编译所有这些,所有编译都很好。但是,运行此 test_node.py
from node_test import test_error_raising
try:
test_error_raising()
except AssertionError:
print("You have assertion error!")
我明白
AssertionError
Exception ignored in: 'Node.Node.remove_parent'
Traceback (most recent call last):
File "test_node.py",line 5,in <module>
test_error_raising()
AssertionError:
系统和版本:
distributor ID: Ubuntu
Description: Ubuntu 20.04.2 LTS
Cython version 0.29.21
Python 3.8.5
解决方法
所以,这个问题很容易解决。应该从 void
函数中删除 cdef
以使其返回正确的错误消息,而不是忽略错误。
原因是当函数被定义为将有void
返回时,错误信息将被创建、报告、销毁并且函数将从异常点返回并且永远不会执行返回语句。>
因此,只需从 void
和 remove_child
中的 remove_parent
和 .pyx
函数中删除 .pxd
将使其行为如预期,错误消息可以正常咳嗽。
更多信息here