Создание исполняемых приложений из скриптов Python

Раздел: Инструменты разработки -> Сборка и компиляция

Компиляция Python: обзор методов

Как скомпилировать Python программу в нативный исполняемый файл с помощью Nuitka?

Nuitka переводит Python код в C/C++ и затем компилирует его в машинный код. Это даёт высокую производительность и возможность распространения без интерпретатора.

Шаги:

  1. Установка Nuitka:
    pip install nuitka

    компиляция программ python (компиляция программ на python)

  2. Создайте простой скрипт hello.py:
    print('Привет, мир!')
  3. Запуск компиляции (для Windows с MinGW):
    nuitka --standalone --mingw64 hello.py
  4. После завершения появится папка hello.dist с исполняемым файлом hello.exe.

Типичные проблемы:

  • Отсутствие компилятора C (MSVC или MinGW). Решение: установить MinGW через choco install mingw или использовать Visual Studio.
  • Ошибки импорта внешних библиотек. Используйте ключ --nofollow-imports для явного включения.
  • Большой размер файла. Примените --lto для оптимизации.

Цель: создание автономного приложения для пользователей без Python.

Как преобразовать Python модуль в расширение C с помощью Cython?

Cython позволяет писать код на Python с аннотациями статических типов, который затем транслируется в C и компилируется в динамическую библиотеку (.pyd/.so).

Пример:

  1. Создайте файл example.pyx:
    def fib(int n):
        cdef int i, a=0, b=1
        for i in range(n):
            a, b = b, a + b
        return a
  2. Подготовьте setup.py:
    from setuptools import setup
    from Cython.Build import cythonize
    
    setup(
        ext_modules = cythonize('example.pyx')
    )
  3. Соберите расширение:
    python setup.py build_ext --inplace
  4. Файл example.cp39-win_amd64.pyd появится в папке. Импортируйте его как обычный модуль.

Типичные проблемы:

  • Ошибки синтаксиса Cython (использование cdef). Решение: изучить документацию.
  • Несовместимость версий Python и Cython. Решение: обновить Cython до последней версии.
  • Проблемы с многопоточностью. Используйте nogil для блоков без GIL.

Цель: ускорение узких мест Python кода.

Как упаковать Python скрипт в один исполняемый файл с помощью PyInstaller?

PyInstaller собирает интерпретатор, зависимости и скрипт в один бинарник. Это не компиляция в машинный код, но часто используется для распространения.

Команда создания одного .exe файла:

pyinstaller --onefile --windowed hello.py

Флаг --windowed убирает консольное окно для GUI приложений. Итоговый файл находится в папке dist.

Типичные проблемы:

  • Большой размер (часто >30 МБ). Решение: используйте UPX для сжатия, --upx-dir.
  • Антивирусы ложно определяют файл как угрозу. Решение: подписать код или добавить в исключения.
  • Отсутствие необходимых файлов (например, изображений). Используйте --add-data для встраивания.

Цель: простое распространение приложения без установки Python.

Как скомпилировать Python скрипты в байт-код .pyc?

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

Пример:

python -m compileall .

Создаются файлы в папке __pycache__. Для ручной компиляции одного файла:

import py_compile
py_compile.compile('my_script.py')

Типичные проблемы:

  • Файлы .pyc не переносимы между версиями Python. Решение: перекомпилировать под целевую версию.
  • Невозможность распространения без интерпретатора. Решение: использовать PyInstaller или Nuitka.

Цель: ускорение запуска больших проектов.

Как перенести Python код в браузер через компиляцию в JavaScript с помощью Transcrypt?

Transcrypt транслирует Python 3.9+ код в JavaScript, сохраняя структуру и позволяя работать с DOM.

Пример:

  1. Установка:
    pip install transcrypt
  2. Создайте hello.py:
    from tkinter import *
    # для веба используется browser модуль
    # но для демонстрации просто:
    print('Hello from Python in browser')
  3. Компиляция:
    transcrypt hello.py
  4. Появится файл hello.js, который можно подключить в HTML.

Типичные проблемы:

  • Ограниченная поддержка стандартной библиотеки (не работает threading). Решение: использовать асинхронные паттерны.
  • Проблемы с производительностью при больших вычислениях. Решение: использовать встроенные JS функции.

Цель: выполнение Python кода на клиенте без серверной части.

Расширенные примеры компиляции

Nuitka: включение внешних библиотек и оптимизация

Рассмотрим компиляцию скрипта, использующего numpy и matplotlib.

Код plot_sin.py:

Пример

import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
plt.plot(x, y)
plt.title('Синусоида')
plt.show()

Команда компиляции с автономным режимом и плагином для Tkinter:

Пример

nuitka --standalone --enable-plugin=tk-inter --output-dir=./build --lto plot_sin.py

Результат:

Создана папка build/plot_sin.dist. Внутри plot_sin.exe (около 60 MB) и все необходимые библиотеки. При запуске отображается окно с графиком.

Возможная ошибка: 'ImportError: No module named 'matplotlib.backends.backend_agg''. Решение: добавить --nofollow-import-to='matplotlib' и вручную скопировать модули, или использовать --include-package=matplotlib.

Cython: ускорение рекурсивного вычисления чисел Фибоначчи

Сравнение чистой реализации Python и Cython с явными типами.

fib_py.py:

Пример

def fib(n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

fib_cy.pyx:

Пример

def fib(int n):
    if n < 2:
        return n
    return fib(n-1) + fib(n-2)

Компиляция с помощью setup.py:

Пример

from setuptools import setup
from Cython.Build import cythonize

setup(ext_modules = cythonize('fib_cy.pyx', compiler_directives={'language_level': '3'}))

Сборка: python setup.py build_ext --inplace

Тест скорости:

Пример

import time
from fib_py import fib as fib_py
from fib_cy import fib as fib_cy

start = time.time()
print(fib_py(35))
print('Python time:', time.time() - start)

start = time.time()
print(fib_cy(35))
print('Cython time:', time.time() - start)

Результат:

9227465
Python time: 2.345 sec
9227465
Cython time: 0.045 sec

Типичная ошибка: Рекурсивный вызов в Cython может быть медленным из-за накладных расходов. Решение: использовать итеративный подход или @cython.cfunc для внутренних функций.

Transcrypt: работа с DOM элементами

Пример скрипта, меняющего содержимое HTML страницы.

Код dom_demo.py:

Пример

# Компиляция: transcrypt -b -n dom_demo.py

from browser import document, window

def change_text():
    document['output'].text = 'Новый текст из Python!'

window.onload = lambda: document['mybutton'].bind('click', change_text)

Соответствующий HTML:

Пример

<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="__target__/dom_demo.js"></script>
</head>
<body>
    <button id="mybutton">Нажми меня</button>
    <div id="output">Исходный текст</div>
</body>
</html>

Результат: при нажатии на кнопку текст в div заменяется.

Ошибка: 'browser' модуль не найден. Решение: убедиться, что Transcrypt установлен и компиляция выполняется с ключом -b (читать документацию).

PyInstaller: добавление ресурсов и иконки

Упаковка приложения с файлом данных и настройкой иконки.

Структура проекта:

Пример

my_app/
  ├── main.py
  ├── data.txt
  └── icon.ico

Код main.py:

Пример

import sys
import os

def resource_path(relative_path):
    """Получить абсолютный путь к ресурсу (для собранного приложения)"""
    if hasattr(sys, '_MEIPASS'):
        return os.path.join(sys._MEIPASS, relative_path)
    return os.path.join(os.path.abspath('.'), relative_path)

with open(resource_path('data.txt'), 'r') as f:
    print(f.read())

Команда сборки:

Пример

pyinstaller --onefile --add-data 'data.txt;.' --icon=icon.ico main.py

Результат: один файл dist/main.exe с встроенным data.txt и иконкой.

Ошибка: 'FileNotFoundError: data.txt' при запуске из собранного exe. Решение: проверить путь с sys._MEIPASS и использовать --add-data корректно (разделитель ';' на Windows, ':' на Linux).

Компиляция программ на Python - comments

En
компиляция программ python (python)