I have some cython classes, and in their cdef
methods, I have assert
statements. However, instead of getting an AssertionError
that I can catch, for example, I get Exception ignored in:
and I cannot catch it (pytest
reports this as warnings as well)
Moreover, other errors happening (other than the assert
one) are not raised and ignored.
As a simple example, let's say I have a Node class called Node.pyx
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)
and its corrisponding Node.pxd
file
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)
As this is all cdef
, it can only be used by another pyx
script or function. So let's have another script testing the nodes, 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)
Now if I compile all of this with cythonize -i *pyx
or a simpel setup script, all compiles well. However, running this test_node.py
from node_test import test_error_raising
try:
test_error_raising()
except AssertionError:
print("You have assertion error!")
I get
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:
System and versions:
Distributor ID: Ubuntu
Description: Ubuntu 20.04.2 LTS
Cython version 0.29.21
Python 3.8.5
So, the problem was fairly easy to solve. One should remove the void
from the cdef
function in order for it to return a proper error message, instead of the error being ignored.
Reason is that when the function is defined that it's going to have void
return, the error message will be created, reported, destroyed and the function will return from the exception point and the return statement will never be executed.
So by just removing the void
from the remove_child
and remove_parent
functions in both .pyx
and .pxd
will make it behave as expected and the error message can be cought normally.
More information here