Как указать источник Python 3 в Cython setup.py?
Я пытаюсь сделать программу "Hello World" на Cython, следуя этому руководству http://docs.cython.org/src/tutorial/cython_tutorial.html#cython-hello-world
Я создал helloworld.pyx
print("Hello World")
и setup.py:
from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_modules = cythonize("helloworld.pyx")
)
Как я могу изменить setup.py, чтобы указать, что моим источником является Python 3, а не Python 2, как в учебнике? Если я вызываю команду "cython" из командной строки, она принимает опцию -3
. Но если я скомпилирую с python setup.py build_ext --inplace
, как показано в руководстве, как мне указать исходный код Python 3? Это может не иметь большого значения для программы Hello World, но будет иметь значение, когда я начну использовать Cython для реальных проектов.
Большое спасибо!
Ответы
Ответ 1
Это правильно, если вы просто вызываете setup.py с Python 3
Использование тестовой программы
print('hello',5,end='**\n') # Python3 syntax, breaks on Python2
Запуск Cython на нем без указания 3 дает
Error compiling Cython file:
------------------------------------------------------------
...
print('hello',5,end='**\n') ^
------------------------------------------------------------
print_something.pyx:1:19: Expected ')', found '='
при компиляции с помощью setup.py, вызванного с помощью python3, строит модуль правильно.
Ответ 2
Можно передать language_level
в качестве опции в cythonize
-function в setup.py
-script:
extensions = cythonize(extensions, compiler_directives={'language_level' : "3"})) # or "2" or "3str"
или если скрипт должен интерпретироваться как language_level=2
Python2 и language_level=3
Python3 (поведение %% cython-magic в IPython):
import sys
# passing 3 or 2 as integer is also accepted:
cythonize(extensions, compiler_directives={'language_level' : sys.version_info[0]})
Другой возможный синтаксис:
extensions = cythonize(extensions, language_level = "3")
Выше может быть удобнее, чем добавить
#cython: language_level=3
для каждого pyx файла в проекте, что может оказаться необходимым, поскольку начиная с Cython 0.29 появляется предупреждение, если language_level
не установлено явно:
/Main.py:367: FutureWarning: директива Cython 'language_level' отсутствует установить, используя 2 на данный момент (Py2). Это изменится в более позднем выпуске! Файл: XXXXXX.pyx
tree = Parsing.p_module(s, pxd, full_module_name)
Поскольку language_level
является глобальной настройкой, декоратор
cimport cython
@cython.language_level("3")
def do_something():
pass
даже не будет цифонизирован.
Ответ 3
Согласно официальной документации по компиляции, уровень языка Python можно указать с помощью директивы через специальный заголовок комментария в верхней части файла, например:
#!python
#cython: language_level=3
Похоже, нет способа указать это в setup.py. Поэтому, если у вас много файлов Cython, вам необходимо добавить директиву компилятора для каждого файла. Хотя единственная ситуация, с которой я столкнулся до сих пор, которая нуждается в этой директиве, - это print(), как в вашем примере, и я широко использовал Cython.
Ответ 4
Если вы используете файл setup.py с расширением, как в этом примере
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
)
Затем вы должны добавить следующий фрагмент кода, чтобы применить директиву language_level:
for e in ext_modules:
e.cython_directives = {'language_level': "3"} #all are Python-3