How to specify Python 3 source in Cython's setup.py?

PythonPython 3.xCython

Python Problem Overview


I am trying to do a "Hello World" program in Cython, following this tutorial http://docs.cython.org/src/tutorial/cython_tutorial.html#cython-hello-world

I created helloworld.pyx

print("Hello World")

and setup.py:

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

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

How can I change setup.py to specify that my source is Python 3, rather than Python 2 like in the tutorial? If I invoke "cython" command from the command line, it accepts -3 option. But if I compile with python setup.py build_ext --inplace like shown in the tutorial, how do I specify Python 3 source? It may not matter much for a Hello World program, but will matter as I start using Cython for real projects.

Python Solutions


Solution 1 - Python

One can pass language_level as an option to the cythonize-function in the setup.py-script:

extensions = cythonize(
               extensions, 
               compiler_directives={'language_level' : "3"})   # or "2" or "3str"
             ) 

Another possible syntax is

extensions = cythonize(extensions, language_level = "3")

The above might be more convenient than to add

#cython: language_level=3

to every pyx-file in the project, which might become necessary because since Cython 0.29 there is a warning, if the language_level isn't set explicitly:

> /Main.py:367: FutureWarning: Cython directive 'language_level' not > set, using 2 for now (Py2). This will change in a later release! File: > XXXXXX.pyx
> tree = Parsing.p_module(s, pxd, full_module_name)


Because language_level is a global setting, the decorator

cimport cython

@cython.language_level("3")
def do_something():
    pass

will not even be cythonized.

Solution 2 - Python

According to official documentation on compilation, the Python language level can be specified using a directive through a special header comment at the top of the file, like this:

#!python
#cython: language_level=3

There doesn't seem to be a way to specify this in setup.py. So if you have many Cython files, you'd have to add the compiler directive to each file. Although the only situation I've met so far that needs this directive is for print() as in your sample, and I've used Cython extensively.

Solution 3 - Python

If you are using a setup.py with Extension, as in this example

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext

ext_modules = [
    Extension("mymodule1",  ["mymodule1.py"]),
    Extension("mymodule2",  ["mymodule2.py"]),
]

setup(
    name = 'My Program Name',
    cmdclass = {'build_ext': build_ext},
    ext_modules = ext_modules
)

then you have to add the following snippet to apply the language_level directive (BEFORE the setup(...), thanks codeman48):

for e in ext_modules:
    e.cython_directives = {'language_level': "3"} #all are Python-3

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrstewardView Question on Stackoverflow
Solution 1 - PythoneadView Answer on Stackoverflow
Solution 2 - PythonYan LiView Answer on Stackoverflow
Solution 3 - PythonGallandView Answer on Stackoverflow