Создание исполняемого файла на Cython
Играл с Cython. Обычно программируют на Python, но использовали C в предыдущей жизни. Я не могу понять, как сделать отдельно стоящий исполняемый файл.
Я скачал cython и могу создать файл.pyx (это просто обычный файл Python с расширением.pyx), который выполняется в оболочке Python, используя: import pyximport; pyximport.install()
Я могу сгенерировать файл.c в командной строке с помощью: cython file.pyx. Я могу сгенерировать файл.so, создав стандартный файл setup.py и выполнив:
setup.py build_ext --inplace
Я пытался сделать исполняемый файл из файла.so с помощью gcc с различными параметрами, но всегда имел массу пропущенных файлов, заголовков и т. Д. Пробовал указывать на заголовки практически везде, но безуспешно, и я не очень знаком с тем, что делают все параметры gcc, или даже если я должен использовать gcc.
У меня возникло отключение из-за того, что я могу запускать свою программу в оболочке Python, но не в командной строке (я не хочу, чтобы пользователи приходили в оболочку, импортировали модули и т. Д.).
Что мне здесь не хватает?
4 ответа
То, что вы хотите, это --embed
флаг для компилятора Cython. Там нет тонны документации, но это то, что я смог найти. Это ссылка на простой рабочий пример.
Чтобы скомпилировать исходный код Cython в файл C, который затем можно скомпилировать в исполняемый файл, вы используете команду типа cython myfile.pyx --embed
и затем скомпилируйте с любым C-компилятором, который вы используете.
Когда вы компилируете исходный код на C, вам все равно нужно будет включить каталог с заголовками Python и ссылку на соответствующую разделяемую библиотеку Python в вашей системе (файл с именем что-то вроде libpython27.so
или же libpython27.a
если вы используете Python 2.7).
Изменить: Вот еще несколько инструкций о том, как получить команды для включения правильных заголовков и ссылки на соответствующие библиотеки.
Как я уже говорил ранее, вам нужно запустить компилятор Cython следующим образом:
cython <cython_file> --embed
Чтобы скомпилировать с помощью gcc, вам нужно найти, где находятся заголовки python в вашей системе (вы можете получить это местоположение, запустив distutils.sysconfig.get_python_inc()
(вам придется импортировать его первым). Это, вероятно, просто /include
подкаталог в вашем каталоге установки Python.
Вам также нужно будет найти общую библиотеку Python. Для Python 2.7 это будет libpython27.a
в Windows или libpython2.7.so
в линуксе
Ваша команда gcc будет тогда
gcc <C_file_from_cython> -I<include_directory> -L<directory_containing_libpython> -l<name_of_libpython_without_lib_on_the_front> -o <output_file_name>
Может быть целесообразно включить -fPIC
флаг. На 64-битных компьютерах с Windows вы также должны будете включить флаги -D MS_WIN64
это говорит MINGW, чтобы скомпилировать для 64-битных окон.
Если вы компилируете что-то, что зависит от NumPy, вам также нужно будет включить каталог, содержащий заголовки NumPy. Вы можете найти эту папку, запустив numpy.get_include()
(опять же после импорта numpy). Ваша команда GCC становится
gcc <C_file_from_cython> -I<include_directory> -I<numpy_include_directory> -L<directory_containing_libpython> -l<name_of_libpython_without_lib_on_the_front> -o <output_file_name>
Это руководство по опциям команды gcc может быть полезным.
Кроме того, я бы порекомендовал вам использовать представления памяти Cython, если это возможно. Это позволит вам не включать заголовки NumPy и включать файл pxd NumPy в файл Cython. Это также упрощает оптимизацию операций нарезки для компилятора C.
Протестировал это на Ubuntu:
устанавливать Cython
используя следующее (Python 2):
sudo apt-get install cython
Для Python 3:
sudo apt-get install cython3
Чтобы скомпилировать код Python в код на C, запустите cython
в cython3
для Python 3):
cython --embed -o example.c example.py
Это сгенерирует example.c
файл.
Теперь скомпилируйте example.c
файл:
gcc -Os -I /usr/include/python2.7 example.c -lpython2.7 -o example
Запустите файл:
./example
Теперь для Python 3 что-то вроде этого будет работать (не проверено):
gcc -Os -I /usr/include/python3.6 example.c -lpython3.6 -o example
где python3.x
версия Python, установленная на вашем компьютере
Это решение для Windows + MS Visual Studio 14 (поскольку никто не упомянул cl.exe
параметров пока нет).
Сначала используйте embed
параметр для получения test.c
файл:
cython test.pyx --embed
Затем скомпилируйте его:
call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64
cl test.c /I C:\Python37\include /link C:\Python37\libs\python37.lib
На выходе получается небольшой исполняемый файл. test.exe
(140 КБ в моем случае для print("Hello World")
).
Заметки:
для приложения с графическим интерфейсом (и без консольного приложения) см. ответ @longgangfan Может ли Cython скомпилироваться в EXE?, т.е. добавить
/subsystem:windows /entry:wmainCRTStartup
вcl.exe
параметры.для получения дополнительной информации о том, существует ли еще исходный код, см. Действительно ли исполняемые файлы, созданные с помощью Cython, свободны от исходного кода? и Содержит ли скомпилированный автономный исполняемый файл Cython весь исходный исходный код?.
кроме того,.exe не запускается сразу на любом компьютере; требуются некоторые другие файлы, см. раздел Минимальный набор файлов, необходимых для распространения кода, скомпилированного с помощью встроенного Cython, и обеспечения его работы на любой машине.
Основываясь на ответе Рафаэля, вот объяснение того, как сделать исполняемый файл «Hello, World» с помощью Cython и Python 3 (проверено на Termux), а затем инструкции для Python 2:
cython3
похоже, это не вариант для моей системы, поэтому вместо этого я делаю следующее:
Файл называется test.py:
print("Hello, world!")
Затем сделайте следующее:
cython -3 --embed -o test.c test.py
Затем вам нужно выяснить, какой путь включения вам нужен, и, возможно, ваши библиотеки.
Я использую Python 3.10.6; поэтому я использую программу python3.10-config для получения информации перед ее вводом в gcc:
python3.10-config --includes
Для меня это выводит это:
-I/data/data/com.termux/files/usr/include/python3.10 -I/data/data/com.termux/files/usr/include/python3.10
Он дал мне один и тот же путь дважды (я не знаю почему), так что просто используйте этот путь (я думаю, вам нужно использовать его только один раз).
Тогда сделайте
python3.10-config --libs
Для меня это выводит это:
-lpython3.10 -lcrypt -ldl -lm -lm
Я не уверен, что каждый из них важен для каждой программы, так как «Hello, world» работает, если я только поставлю-lpython3.10
.
Во всяком случае, тогда я делаю это, и это дает мне исполняемый файл:
gcc -Os -I/data/data/com.termux/files/usr/include/python3.10 test.c -lpython3.10 -o test
Также есть программа под названием python2.7-config.
Если я хочу получить исполняемый файл с Python 2.7.18, я могу сделать это вместо вышеописанного:
cython -2 --embed -o test.c test.py
Затем
python2.7-config --includes
python2.7-config --libs
Это дает мне это:
-
-I/data/data/com.termux/files/usr/include/python2.7 -I/data/data/com.termux/files/usr/include/python2.7
-
-lpython2.7 -ldl -lm
Наконец, я делаю это, чтобы получить исполняемый файл:
gcc -Os -I/data/data/com.termux/files/usr/include/python2.7 test.c -lpython2.7 -o test