[Cython] Safer default exception handling with return type annotations?

Robert Bradshaw robertwb at gmail.com
Wed Sep 6 01:21:53 EDT 2017

On Mon, Sep 4, 2017 at 12:32 PM, Stefan Behnel <stefan_ml at behnel.de> wrote:
> Hi all,
> since PEP 484 type annotations are scheduled for the next release now, I
> wonder if we should take the opportunity to change the defaults for the
> exception handling of typed cdef functions.
> Currently, if you define a function like this:
>     cdef int func():
>         raise ValueError()
> It will not actually raise the error but print and ignore it. In order to
> make it safe, you have to say
>     cdef int func() except -1:
>         raise ValueError()

A huge +1 to making exception propagation implicitly the default.
(Would we want to introduce syntax to preserve the old behavior
though?) There is the downside of a slight performance regression (we
should measure exactly how slight) and leaving the exception set
(which could actually be desirable) but exception swallowing is almost
never what a user wants.

> It has always been like this, but with PEP 484 type annotations, it becomes
> much nicer to keep Cython code Python compatible and actually running in
> Python, so that the following is safe when interpreted but not when compiled:
>     @cython.cfunc
>     def func(x: cython.int) -> cython.int:
>         if x < 0:
>             raise ValueError()
>         return x * 2
> Since this is new syntax, and no code exists yet that uses it, it would be
> safe to change the default here, and to automatically declare this function
> as "except? -MIN_INT", for example. The same applies to functions returning
> pointers ("except? NULL") or even structs, which could be declared "except *".
> This would lead to inconsistencies within Cython, but I think the use case
> of Python compatible behaviour is important enough to consider this, and
> for code using this syntax, it also feels less likely that the caller is
> actual C code that couldn't handle that exception.

I'm not a huge fan of behaving differently depending on what syntax
was used to annotate the return type--I'd rather they be 100% aliases
of each other.

I would be willing to consider letting un-annotated extern functions
have different defaults than non-extern ones. This would, of course,
make the two type signatures incompatible (though presumably an
except? could be used wherever a noexcept one is needed.

More information about the cython-devel mailing list