Alex Gaynor
Alex Gaynor

Reputation: 15029

Reraising an exception in Cython on Python 2 and Python3

I have some Cython code that currently looks

exc = sys.exc_info()
raise exc[0], exc[1], exc[2]

This doesn't work on Python3, since the "raise from tuple" form is no longer allowed. Were this normal Python code, I would just use six.reraise, but that's not available to me here. What's the Cython friendly way to do the same, which works on both Python2 and Python3?

Upvotes: 5

Views: 667

Answers (1)

lothario
lothario

Reputation: 1868

One great Cython feature is that the generated C code can be compiled for either Python 2 or Python 3. So your example above will work with either version of Python, unmodified.

You can tell Cython to compile code assuming Python 2 syntax and semantics (the -2 argument, which is on by default) or assuming Python 3 (the -3 argument). In either case, the resulting extension module source code can be compiled and used for Python 2 or Python 3, as long as the dynamic components (imports, etc.) are compatible.

For example:

def raises_exception():
    raise KeyError("what you doin'?")


def foobar():
    try:
        raises_exception()
    except Exception:
        import sys
        exc = sys.exc_info()
        raise exc[0], exc[1], exc[2]

Here's a setup.py that will work on either Py2 or Py3:

from distutils.core import setup
from Cython.Build import cythonize

setup(ext_modules=cythonize("reraise.pyx"))

I can run python setup.py build_ext -i on either version of Python (provided I have cython installed for each), and the resulting extension module will work.

$ python setup.py build_ext -i # Py3 python

$ ipython3
Python 3.3.2 (v3.3.2:d047928ae3f6, Oct  4 2013, 15:49:17)
Type "copyright", "credits" or "license" for more information.

IPython 1.2.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import reraise

In [2]: reraise.foobar()
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-2-9e20eacfd84e> in <module>()
----> 1 reraise.foobar()

/.../reraise.so in reraise.foobar (reraise.c:916)()

/.../reraise.so in reraise.foobar (reraise.c:847)()

/.../reraise.so in reraise.raises_exception (reraise.c:762)()

KeyError: "what you doin'?"

In [3]:

Upvotes: 4

Related Questions