pythoncythoncythonize

'Exception ignored in:' cython extension classes and their `cdef` methods


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

Solution

  • 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