Как скомпилировать программу на python
Перейти к содержимому

Как скомпилировать программу на python

  • автор:

py_compile — Compile Python source files¶

The py_compile module provides a function to generate a byte-code file from a source file, and another function used when the module source file is invoked as a script.

Though not often needed, this function can be useful when installing modules for shared use, especially if some of the users may not have permission to write the byte-code cache files in the directory containing the source code.

exception py_compile. PyCompileError ¶

Exception raised when an error occurs while attempting to compile the file.

py_compile. compile ( file , cfile = None , dfile = None , doraise = False , optimize = — 1 , invalidation_mode = PycInvalidationMode.TIMESTAMP , quiet = 0 ) ¶

Compile a source file to byte-code and write out the byte-code cache file. The source code is loaded from the file named file. The byte-code is written to cfile, which defaults to the PEP 3147/ PEP 488 path, ending in .pyc . For example, if file is /foo/bar/baz.py cfile will default to /foo/bar/__pycache__/baz.cpython-32.pyc for Python 3.2. If dfile is specified, it is used instead of file as the name of the source file from which source lines are obtained for display in exception tracebacks. If doraise is true, a PyCompileError is raised when an error is encountered while compiling file. If doraise is false (the default), an error string is written to sys.stderr , but no exception is raised. This function returns the path to byte-compiled file, i.e. whatever cfile value was used.

The doraise and quiet arguments determine how errors are handled while compiling file. If quiet is 0 or 1, and doraise is false, the default behaviour is enabled: an error string is written to sys.stderr , and the function returns None instead of a path. If doraise is true, a PyCompileError is raised instead. However if quiet is 2, no message is written, and doraise has no effect.

If the path that cfile becomes (either explicitly specified or computed) is a symlink or non-regular file, FileExistsError will be raised. This is to act as a warning that import will turn those paths into regular files if it is allowed to write byte-compiled files to those paths. This is a side-effect of import using file renaming to place the final byte-compiled file into place to prevent concurrent file writing issues.

optimize controls the optimization level and is passed to the built-in compile() function. The default of -1 selects the optimization level of the current interpreter.

invalidation_mode should be a member of the PycInvalidationMode enum and controls how the generated bytecode cache is invalidated at runtime. The default is PycInvalidationMode.CHECKED_HASH if the SOURCE_DATE_EPOCH environment variable is set, otherwise the default is PycInvalidationMode.TIMESTAMP .

Changed in version 3.2: Changed default value of cfile to be PEP 3147-compliant. Previous default was file + ‘c’ ( ‘o’ if optimization was enabled). Also added the optimize parameter.

Changed in version 3.4: Changed code to use importlib for the byte-code cache file writing. This means file creation/writing semantics now match what importlib does, e.g. permissions, write-and-move semantics, etc. Also added the caveat that FileExistsError is raised if cfile is a symlink or non-regular file.

Changed in version 3.7: The invalidation_mode parameter was added as specified in PEP 552. If the SOURCE_DATE_EPOCH environment variable is set, invalidation_mode will be forced to PycInvalidationMode.CHECKED_HASH .

Changed in version 3.7.2: The SOURCE_DATE_EPOCH environment variable no longer overrides the value of the invalidation_mode argument, and determines its default value instead.

Changed in version 3.8: The quiet parameter was added.

A enumeration of possible methods the interpreter can use to determine whether a bytecode file is up to date with a source file. The .pyc file indicates the desired invalidation mode in its header. See Cached bytecode invalidation for more information on how Python invalidates .pyc files at runtime.

New in version 3.7.

The .pyc file includes the timestamp and size of the source file, which Python will compare against the metadata of the source file at runtime to determine if the .pyc file needs to be regenerated.

The .pyc file includes a hash of the source file content, which Python will compare against the source at runtime to determine if the .pyc file needs to be regenerated.

Like CHECKED_HASH , the .pyc file includes a hash of the source file content. However, Python will at runtime assume the .pyc file is up to date and not validate the .pyc against the source file at all.

This option is useful when the .pycs are kept up to date by some system external to Python like a build system.

Command-Line Interface¶

This module can be invoked as a script to compile several source files. The files named in filenames are compiled and the resulting bytecode is cached in the normal manner. This program does not search a directory structure to locate source files; it only compiles files named explicitly. The exit status is nonzero if one of the files could not be compiled.

Positional arguments are files to compile. If — is the only parameter, the list of files is taken from standard input.

Превращаем код на Python в исполняемый EXE-файл

Обычно код на Питон запускают двумя способами: через терминал или через текстовый редактор / IDE.

При этом стоит отметить, что файлик Python — это всего лишь скрипт, который сохранён в расширении .py. Да, это очевидно, но в этом и кроется проблема: иногда нужно скрыть исходный код, а поделиться программкой (в виде альфа-версии, например) очень хочется.

Одно из решений, которое закрывают боль с исходным кодом — это конвертация файла Python в исполняемый exe-файлик.

В этой статье мы научимся создавать «экзешники» при помощи двух библиотек: Pyinstaller and auto-py-to-exe.

Перед тем, как продолжить чтение статьи, скачайте этот репозиторий. Он здорово поможет вам понять процесс, если вы будете повторять все шаги вместе с нами.

Почему возникает потребность конвертировать Python-код в EXE

  1. Код могут украсть. Об этом мы уже говорили выше. Куда проще достать исходный код непосредственно из py-файла, чем из скомпилированного приложение. Py-файл достаточно просто открыть!
  2. Хочется поделиться кодом с другими юзерами. Дело не только в том, что ваш код могут украсть. Зачастую код содержит зависимости, которыми должен владеть другой юзер перед запуском вашего Python-кода. Но что, если он вообще ничего не смыслит в программировании? Не заставишь ведь его сперва выучить программирование, чтобы оценить ваше новое суперприложение. Проще создать исполняемый файл.
  3. Исполняемый файл можно запускать автоматически, по расписанию. Этот пункт актуален, если вы решили написать утилиту для вашего ПК, и эта утилита должна запускаться либо в определенное время, либо вместе с запуском ОС.

Конвертация кода Python в файл .exe

Для начала создадим скрипт на Python. В качестве примера мы используем открытый код бронирования жилья AitBnb в Нью-Йорке. Если у вас уже есть готовый код, можете сразу использовать его.

Вы не забыли скачать библиотеки по ссылке по введении? Сделайте это сейчас.

Вот структура файлов на GitHub:

Каждая из директорий должна обладать своей виртуальной средой. Убедитесь, что среды развёрнуты и в директории pyinstaller, и в auto-py-to-exe.

Сохраните ваш код и скопируйте его в обе директории.

Что делать в Pyinstaller

Ещё раз убедитесь, что виртуальная среда развёрнута. Да, мы настаиваем. Проверьте, установлены ли все зависимости между библиотеками и кодом.

Всё в порядке? Запускайте команду:

Процесс должен запуститься, и в конце консоль сообщит: «Completed successfully». Значит, всё прошло успешно. ��

Успешный процесс компиляции в Pyinstaller // DataCamp

В папке с бибилотекой и кодом должны появиться две новые директории под названиями build и dist. В папке dist вы найдёте заветный exe-файл. Запустите его и проверьте работу приложения.

Что делать в Auto-py-to-exe

Также скиньте файлик с кодом в папку с библиотекой и проверьте зависимости между кодом и библиотекой.

Как скомпилировать Python

Я хочу рассказать об удивительном событии, о котором я узнал пару месяцев назад. Оказывается, одна популярная python-утилита уже более года распространяется в виде бинарных файлов, которые компилируются прямо из python. И речь не про банальную упаковку каким-нибудь PyInstaller-ом, а про честную Ahead-of-time компиляцию целого python-пакета. Если вы удивлены так же как и я, добро пожаловать под кат.

Объясню, почему я считаю это событие по-настоящему удивительным. Существует два вида компиляции: Ahead-of-time (AOT), когда весь код компилируется до запуска программы и Just in time compiler (JIT), когда непосредственно компиляция программы под требуемую архитектуру процессора осуществляется во время ее выполнения. Во втором случае первоначальный запуск программы осуществляется виртуальной машиной или интерпретатором.

Если сгруппировать популярные языки программирования по типу компиляции, то получим следующий список:

Ahead-of-time compiler: C, C++, Rust, Kotlin, Nim, D, Go, Dart;

Just in time compiler: Lua, С#, Groovy, Dart.

В python из коробки нет JIT компилятора, но отдельные библиотеки, предоставляющие такую возможность, существуют давно

Смотря на эту таблицу, можно заметить определенную закономерность: статически типизированные языки находятся в обеих строках. Некоторые даже могут распространяться с двумя версиями компиляторов: Kotlin может исполняться как с JIT JavaVM, так и с AOT Kotlin/Native. То же самое можно сказать про Dart (версии 2). A вот динамически типизированные языки компилируются только JIT-ом, что впрочем вполне логично.

При запуске виртуальная машина сначала накапливает информацию о типах переменных, затем после накопления статистики, запускается компиляция наиболее нагруженных частей программы. Виртуальная машина отслеживает типы аргументов и переключает выполнение программы между уже скомпилированными и не скомпилированными участками кода в зависимости от текущих значений переменных.

При использовании JIT компиляции типы не очень то и нужны, ведь информация о типах собирается во время работы программы. Поэтому все популярные динамически типизированные языки программирования распространяются именно с JIT компилятором. Но как быть с AOT компиляцией кода, в котором нет типов? Меня очень заинтересовал этот вопрос, и я полез разбираться.

Итак, вернемся к утилите, о которой говорилось в начале статьи. Речь про mypy — наиболее популярный синтаксический анализатор python-кода.

С апреля 2019 года эта утилита распространяется в скомпилированном виде, о чем рассказывается в блоге проекта. А для компиляции используется еще одна утилита от тех же авторов — mypyc. Погуглив немного, я нашел достаточно большую статью “Путь к проверке типов 4 миллионов строк Python-кода” про становление и развитие mypy (на Хабре доступен перевод: часть 1, часть 2, часть 3). Там немного рассказывается о целях создания mypyc: столкнувшись с недостаточной производительностью mypy при разборе крупных python-проектов в Dropbox, разработчики добавили кеширование результатов проверки кода, а затем возможность запуска утилиты как сервиса. Но исчерпав очевидные возможности оптимизации, столкнулись с выбором: переписать все на go или на cython. В результате проект пошел по третьему пути — написание своего AOT python-компилятора.

Дело в том, что для правильной работы mypy и так необходимо построить то же синтаксическое дерево, что и интерпретатору во время исполнения кода. То есть mypy уже “понимает” python, но использует эту информацию только для статистического анализа, а вот mypyc может преобразовывать эту информацию в полноценный бинарный код.

Думаю тут многие решили, что разобрались в вопросе того, как скомпилировать динамически типизированный python-код. Python c версии 3.4 поддерживает аннотацию типов, а mypy как раз и используется для проверки корректности аннотаций. Получается, python как бы уже и не динамически типизированный язык, что позволяет применить AOT компиляцию. Но загвоздка в том, что mypyc может компилировать и неаннотированный код!

Функция bubble_sort

Для примера рассмотрим функцию сортировки “пузырьком”. Файл lib.py:

У типов нет аннотаций, но это не мешает mypyc ее скомпилировать. Чтобы запустить компиляцию, нужно установить mypyc. Он не распространяется отдельным пакетом, но если у вас установлен mypy, то и mypyc уже присутствует в системе! Запускаем mypyc, следующей командой:

После запуска в проекте будут созданы следующие директории:

.mypy_cache — mypy кэш, mypyc неявно запускает mypy для разбора программы и получения AST;

build — артефакты сборки;

lib.cpython-38-x86_64-linux-gnu.so — собственно сборка под целевую платформу. Данный файл представляет из себя готовый CPython Extension.

CPython Extension — встроенный в CPython механизм взаимодействия с кодом, написанным на С/C++. По сути это динамическая библиотека, которую CPython умеет загружать при импорте нашего модуля lib. Через данный механизм осуществляется взаимодействие с модулями, написанными на python.

Компиляция состоит из двух фаз:

Компиляция python кода в код С;

Компиляция С в бинарный .so файл, для этого mypyc сам запускает gcc (gcc и python-dev также должен быть установлены).

Файл lib.cpython-38-x86_64-linux-gnu.so имеет преимущество перед lib.py при импорте на соответствующей платформе, и исполняться теперь будет именно он.

Ну и давайте сравним производительность модуля до и после компиляции. Для этого создадим файл main.py с кодом запуска сортировки:

Получим примерно следующие результаты:

Ожидаемо скомпилированный код оказался быстрее (

в 2 раза), что неплохо, так как для такого результата нам потребовалось запустить лишь одну команду. Хотя от скомпилированного кода привычно ожидаешь большего.

Чтобы ответить на вопрос “как компилируется динамически типизированный код”, придется заглянуть в представление этой функции на С. Но разобрать ее будет достаточно сложно, поэтому давайте попробуем разобраться с примером попроще.

Функция sum(a, b)

Скомпилируем функцию суммы от двух переменных:

Перед запуском компиляции я ожидал увидеть примерно следующий код на С:

Однако результат оказался cущественно иным (код немного упрощен):

Рассмотрим, что тут происходит. Во-первых, так как мы не знаем типы входных переменных, функция в качестве аргументов принимает указатели на объекты класса PyObject, по сути это внутренние CPython структуры. Далее компилятор должен сложить эти объекты, но как, если настоящие типы аргументов неизвестны во время компиляции: это могут быть целые числа, числа с плавающей точкой, списки и вообще не факт, что аргументы можно складывать, тогда нужно вернуть ошибку. И что же делает в этом случае mypyc?

Как оказалось, все очень просто: он просит CPython самостоятельно сложить эти аргументы. Функция PyNumber_Add — это внутренняя функция СPython, которая доступна из расширения, ведь СPython отлично умеет складывать свои объекты.

Взаимодействие CPython c Extension можно изобразить следующим диалогом:

— А посчитай-ка мне функцию sum для A, B;

— Хорошо, но скажи сначала, сколько будет A + B;

— Будет С;

— Хорошо, тогда держи ответ — С.

Вот такой нехитрый прием используется при компиляции динамического кода: компилируем все, что можем, а все остальное отдаем интерпретатору.

Конечно, данный пример выглядит гротескно, но даже несмотря на такую неэффективность, mypyc позволяет добиться существенного прироста производительности, как в примере с сортировкой.

Функция sum(a: int, b: int)

Итак, у нас получилось скомпилировать python, и мы разобрались с тем, как это работает, а также увидели определенную неэффективность полученного результата. Теперь попробуем разобраться в том, как можно это улучшить. Очевидно, что основная проблема заключается во множественном взаимодействии CPython — Extension. Но как это побороть?

Для повышения эффективности, нужно, чтобы расширение, получив управление, могло как можно дольше оставлять его у себя без обращения к CPython. Если бы у mypyc была информация о типах переменных, то он бы мог самостоятельно произвести сложение без возврата управления. Но вывести типы самостоятельно mypyc не может, он даже не контролирует код, из которого осуществляется вызов функции sum. Соответственно, ему нужно помочь, проставив аннотации вручную. Давайте посмотрим, как поменяется результирующая С-функция, если добавить аннотацию типов:

Скомпилированный результат на C (немного очищенный):

Главное, что можно заметить: функция существенно поменялась, а значит, компилятор реагирует на появление аннотации. Давайте разбираться, что изменилось.

Теперь CPyDef_sum получает на вход не указатели на PyObject, а структуры CPyTagged. Это все еще не int, но уже и не часть CPython, а часть библиотек mypyc, которую он добавляет в скомпилированный код расширения. Для ее инициализации в рантайме сначала проверяется тип, так что теперь функция sum работает только с int и обойти аннотацию не получится.

Далее происходит вызов CPyTaggetAdd вместо PyNumber_Add. Это уже внутренняя функция mypyc. Если заглянуть в код CPyTaggetAdd, то можно понять, что там происходит проверка диапазонов значений a и b, и если они укладываются в int, то происходит простое суммирование, а также проверка на переполнение:

Таким образом, наш диалог CPython — Extension превращается из абсурдного в нормальный:

— А посчитай-ка мне функцию sum для A, B;

— Хорошо, тогда держи ответ С.

Функция bubble_sort(data: List[int])

Настало время вернуться к функции сортировки, чтобы провести замеры скорости. Изменим начальную функцию, добавив аннотацию для data:

Из Py в исполняемый файл: как провести компиляцию

Python – популярный язык разработки, который стал пользоваться спросом в последние несколько лет. Он достаточно прост в изучении, но в некоторых его особенностях непросто разобраться даже опытному программисту.

Изначально Python создает приложение в формате .py. Это не совсем удобно, особенно если пользователь имеет дело в Windows. Для комфортной проверки и формирования утилиты нужно скомпилировать py в exe. Добиться соответствующего результата удается несколькими способами. О них и зайдет речь далее. Предложенные сведения пригодятся всем, кто планирует писать программы на Питоне.

О формате executable

Exe – это формат исполняемого типа. Он знаком всем, кто хотя бы раз запускал MS Windows. Представляет собой набор инструкций, который заставляет компьютер выполнить ту или иную задачу. Не важно, на каком языке написана программа – Питон, C++ или Java. Если проект скомпилирован в exe, он будет успешно прочтен устройством.

Перед тем как думать, как скомпилировать python в exe файл, нужно понимать – создание подобного документа нацелено «на машину». Экзешник считывается устройством, базируется на машинном коде.

Данный вариант применяется в различных операционных системах:

  • Windows;
  • DOS;
  • Symbian;
  • OS/2.

Может предусматривать в своем составе метаданные, включая цифровые подписи. Для обычного пользователя исполняемый файл – это готовое к запуску приложение, которое остается установить или активировать.

Способы преобразования проекта

Python скрипт в exe перевести не слишком сложно. Сборка может проходить как автоматически, так и при помощи online/offline приложений. Все зависит от личных предпочтений разработчика.

Создать исполняемый файл на Питоне (экзешник) – дело нескольких минут. Далее будут представлены популярные и известные методы, позволяющие преобразовывать Python Script в интересующий формат.

Auto PY

Первый вариант – один из самых простых. Он позволит сделать исполняемый файл в несколько кликов. Речь идет об использовании приложения, которое носит название «компилятор». Это – Auto PY to EXE.

Перевод проекта через соответствующее ПО с Python в экзешник позволит запускать утилиты на других машинах. Для этого не нужно предварительно устанавливать Питон.

Инициализация

Чтобы сделать исполняемый файл соответствующим способом, нужно провести инициализацию Auto PY to EXE. Первый вариант – установка «в командной строке». Для этого требуется ввести команду: pip install auto-py-to-exe.

Второй вариант – через GitHub. Для этого нужно:

  1. Клонировать репозиторий .
  2. Перейти в папку с соответствующим компилятором .
  3. Запустить файл setup.py.
  4. Проверить актуальную версию.
  5. Открыть прогу (Python Scripts), с которой планируется дальнейшая работа. Процесс осуществляется в терминале .

Установка завершена. Конвертер готов к непосредственному использованию. Теперь можно сделать исполняемый файл из Python в несколько кликов.

Преобразование

Создание экзешника (executables) из Питоновского project проводится в несколько этапов:

  1. Добавляем в конвертор местоположение файла. На этом этапе прописывается путь, где лежит интересующий пользователя скрипт. Нужно перейти к местоположению документа и добавить соответствующий «адрес».
  2. Выбор директории. One Directory создаст папку со всеми необходимыми документами и одним исполняемым, когда будет обрабатывать скрипт.
  3. Определить тип приложения. На данном этапе предлагается создать документ или консольного типа, или оконного. Windows Based – вариант, который скроет console. Компиляция типа Console Based используется, если мы преобразуем script, предусматривающий работу с консолью. Window Based – это вариант для GUI.
  4. Компиляция. Здесь компилируем project. На экране появятся дополнительные опции. Их выбор зависит от предпочтений разработчика. Чтобы начать процедуру, необходимо нажать на кнопку Convert.

Completed Project через Auto PY to EXE разместится в отдельной папке. По умолчанию – это место, откуда запускался converter. В папке множество документов, но всего один – с интересующим форматом. При двойном нажатии на него будет запускаться программа на Python.

Py Installer

Сборка exe file может проводиться через компилятор Pyinstaller. Установка – через pip. После этого рекомендуется проверить build компилятора – лишь после делать все необходимые манипуляции. Команда pip install PyInstaller поможет активировать «утилиту». Она включена в стандартный пакет Python. Сохранить py file to exe будет проще простого.

Как собрать проект

Конвертер позволяет сохранить весь проект в единый Python-файл. Создание (сборка) происходит так:

  1. Считывается скрипт.
  2. Активируется код для выявления зависимостей.
  3. Создается файл spec. Он включает в себя название скрипта, библиотеку-зависимости, иные документы.
  4. Converter собирает копии библиотек и файлов вместе с активным интерпретатором Python.
  5. Для того, чтобы перевести код (script) в file исполняемого типа, создается папка Build. В ней фиксируются логи и рабочие документы.
  6. Создается папка DIST. Она расположена в папке со скриптом. Этот этап пропускается при наличии соответствующего компонента.
  7. Сохраняем через converter необходимые документы вместе со скриптом в одну папку или исполняемый файл.

Если задействовать onedir или -D при генерации, code и его files разместятся в одной папке. Это – настройки по умолчанию. Применение onefile или -F – это создание сохранений в едином документе.

Пример

Convert Python код в exe – не так трудно. Все installing и compile code отнимают некоторое время, но требуют минимального вмешательства. Вот – пример того, как перевести (create build) исходный код в интересующую форму:

  1. Дан документ simple.py .
  2. Ввести в командной строке pyinstaller –onefile simple.py.
  3. Дождаться завершения процесса.

Это – compile (возможность сохранить) Python projects code on исполняемый документ. Установка завершится – появятся папки built и dist. А еще – новый spec-файл.

Py2exe

Есть еще поход – convert (compile) coding через Py2exe. Подойдет для Питона 3.4 и версий ниже. Сначала creates визуальное окружение, затем – сохраняем picture и иные компоненты скрипта в единое целое. Приведенный пример – проект с именем myenv.

Для converting python auto py to документ exe, нужно:

  1. Creating визуальное окружение .
  2. Installed py2 exe .
  3. Completed process by creating «windowed» file. В виртуальном окружении выполняется команда .

В ходе процесса сохраняется готовый скрипт. Он при запуске будет открываться и закрываться очень быстро. Чтобы converted файл не закрывал терминал, нужно добавить строчку в документе Питона.

В сети

Задумываясь, как сделать exe из Python, можно created building при помощи online converts. Это специализированные компиляторы, работающие в интернете. Online сервисы не требуют install, функционируют так:

  1. На экране появляется главное окно — main line.
  2. В окне compiler нужно ввести скрипт.
  3. Нажать на кнопку Installation. Иногда – Compiled или Run.
  4. Online сервис compiles файл интересующего формата. Иногда его можно выбрать. При ошибке обработки операции на экране появится надпись «failed».

Остается скачать compiling документацию и (или) его проект с полноценной папкой. Можно запускать документ.

А вот – туториал, в котором наглядно показано, как из файла py сделать exe. Лучше разобраться в теме помогут специализированные онлайн-курсы.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *