Как превратить .py в exe: сборка исполняемого файла из Python

Как превратить .py в exe: сборка исполняемого файла из Python Полезное

Упаковка Python в exe (freezing) — это сборка скрипта .py, интерпретатора Python и всех его зависимостей в один исполняемый файл, который запускается на машине без установленного Python. Важно сразу развести термины: почти все, что называют «компиляцией py в exe», на деле является именно упаковкой, а не переводом кода в машинные инструкции. Ниже разберу, что происходит внутри, какие инструменты брать в 2026 году под конкретную задачу, соберу exe через PyInstaller шаг за шагом и покажу, что делать, когда файл не запускается. Код в статье прогнан, вывод под ним реальный.

Компиляция или упаковка: что реально происходит

Когда вы запускаете python hello.py, интерпретатор сначала переводит исходник в промежуточный байткод (файлы .pyc), а затем выполняет его на виртуальной машине CPython. Готового машинного кода под процессор здесь не появляется — байткод исполняет сам интерпретатор.

Инструменты вроде PyInstaller не меняют эту схему. Они берут ваш байткод, добавляют к нему интерпретатор и нужные библиотеки и «замораживают» все это в один файл. Такой процесс называют freezing (заморозка, упаковка), а не компиляцией. Внутри exe по-прежнему лежит байткод, который на запуске распаковывается и исполняется встроенным интерпретатором.

Цепочка получается такая: исходник .py -> байткод .pyc -> упаковка вместе с интерпретатором -> один исполняемый файл. Настоящая компиляция в машинный код — это отдельный сценарий: его закрывает Nuitka, о нем ниже.

Разница практичная. Упакованный exe весит десятки мегабайт (внутри целый интерпретатор) и работает с той же скоростью, что и обычный скрипт. Скомпилированный Nuitka файл тяжелее собрать, но он ближе к нативному коду и лучше скрывает исходник.

Инструменты 2026: что взять под задачу

Выбор зависит не от «самого нового» инструмента, а от задачи. Ориентир ниже.

Задача Что взять Когда иначе
Быстро собрать exe из скрипта под текущую ОС PyInstaller нужна графическая настройка сборки
Настраивать сборку мышкой, без флагов в консоли auto-py-to-exe нужен только результат в CI/скриптом
Настоящая компиляция в машинный код, скорость и защита исходника Nuitka нужна максимально простая и быстрая сборка
Проект с классической установкой через setup-скрипт cx_Freeze достаточно одной команды PyInstaller
Только Windows, историческая совместимость py2exe переносимость на macOS/Linux (py2exe их не умеет)

Важная оговорка: PyInstaller, auto-py-to-exe и cx_Freeze — это упаковщики (freezers), они не превращают Python в машинный код. Реальную компиляцию делает только Nuitka. Онлайн-сервисы «py to exe» я не рекомендую: вы загружаете свой код на чужой сервер, а результат непредсказуем по составу и безопасности.

Сборка через PyInstaller шаг за шагом

PyInstaller — самый ходовой вариант. Дорожная карта до готового артефакта dist/hello.exe:

  1. Установить: pip install pyinstaller.
  2. Подготовить рабочий скрипт (пример ниже).
  3. Собрать: pyinstaller --onefile hello.py.
  4. Забрать exe из появившейся папки dist.

Возьмем минимальный, но полностью рабочий скрипт hello.py:

# hello.py - маленькое приложение, которое соберем в exe
def greet(name):
    return f"Привет, {name}! Это приложение запущено из собранного файла."


if __name__ == "__main__":
    print(greet("мир"))
    print("2 + 2 =", 2 + 2)

При обычном запуске python hello.py он выводит:

Привет, мир! Это приложение запущено из собранного файла.
2 + 2 = 4

Теперь команда сборки. Флаг --onefile (короткий -F) складывает все в один файл:

pyinstaller --onefile hello.py

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

... INFO: Building EXE from EXE-00.toc completed successfully.

После этого рядом появятся папки build (рабочие файлы и логи) и dist (готовый результат), а также файл hello.spec с параметрами сборки. Исполняемый файл лежит в dist: на Windows это dist\hello.exe, на macOS и Linux — файл dist/hello без расширения. Запуск dist\hello.exe выведет ровно те же две строки, что и скрипт выше.

Ключевое ограничение: кросс-компиляции здесь нет. PyInstaller собирает exe только под ту ОС, на которой запущен. Чтобы получить Windows-exe, нужен Windows (реальный, виртуальная машина или Windows-раннер в CI); собрать его из-под macOS одной командой не выйдет.

onefile или onedir

У PyInstaller два режима вывода, и выбор между ними — частый вопрос.

Режим Флаг Что получается Когда брать
Один файл --onefile / -F единственный exe удобно раздавать, но запуск чуть медленнее (распаковка во временную папку)
Папка --onedir / -D exe плюс папка с библиотеками быстрее стартует, проще отлаживать; по умолчанию

Еще один полезный флаг — --noconsole (он же --windowed): он прячет черное окно консоли и нужен для программ с графическим интерфейсом. Для консольных утилит его, наоборот, не ставят, иначе вы не увидите вывод и ошибки.

auto-py-to-exe: та же сборка мышкой

auto-py-to-exe — это не отдельный компилятор, а графическая надстройка над PyInstaller. Устанавливается через pip install auto-py-to-exe, запускается одноименной командой и открывает окно, где вы выбираете скрипт, режим (onefile или onedir), наличие консоли и иконку. По кнопке «Convert .py to .exe» программа собирает те же флаги PyInstaller и вызывает его за вас. Если разобрались с PyInstaller в консоли, auto-py-to-exe не даст ничего нового, кроме удобства настройки.

Настоящая компиляция: Nuitka

Если под «компиляцией» вы имеете в виду именно перевод в машинный код, это делает Nuitka. Она транслирует ваш Python в код на C, а затем собирает его системным компилятором C в нативный исполняемый файл.

Устанавливается через pip install nuitka, для сборки нужен установленный компилятор C (на Windows Nuitka умеет сама подтянуть подходящий MinGW). Базовая команда для одного файла:

python -m nuitka --onefile hello.py

Плюсы против упаковщиков: результат обычно быстрее на вычислительной нагрузке и надежнее скрывает исходный код, потому что готового байткода внутри уже нет. Минусы: сборка дольше и требует рабочего компилятора C. Nuitka — разумный выбор, когда важны скорость или защита кода; для «просто собрать exe» PyInstaller проще.

Данные и ресурсы внутри exe

Частая проблема после сборки: программа искала рядом файл (картинку, конфиг, data.txt), а в собранном exe его «не находит». Причина в том, что в режиме --onefile PyInstaller распаковывает вложенные файлы во временную папку, путь к которой лежит в sys._MEIPASS, а не в папке со скриптом.

Универсальный помощник, который работает и при обычном запуске, и внутри собранного файла:

import sys
import os


def resource_path(rel_path):
    # sys._MEIPASS есть только внутри onefile-сборки PyInstaller;
    # при обычном запуске берем папку самого скрипта
    base = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__)))
    return os.path.join(base, rel_path)


print("frozen:", getattr(sys, "frozen", False))
print("имя файла ресурса:", os.path.basename(resource_path("data.txt")))

Вне сборки скрипт выводит:

frozen: False
имя файла ресурса: data.txt

Флаг sys.frozen установлен только внутри собранного приложения, поэтому по нему код понимает, где именно он выполняется. Сам файл data.txt в сборку нужно явно добавить флагом --add-data, иначе внутри exe его просто не будет.

Если сборка не запускается: диагностика по симптому

  • Окно мелькает и сразу закрывается. Так ведет себя консольный exe, запущенный двойным кликом: программа отработала и вышла. Запускайте из уже открытой консоли или добавьте в конце input(), чтобы увидеть вывод.
  • Антивирус удаляет или блокирует exe. Частое ложное срабатывание на загрузчик PyInstaller в режиме onefile. Помогает сборка в режиме --onedir, обновление PyInstaller до свежей версии и добавление файла в исключения.
  • ModuleNotFoundError при запуске, хотя скрипт работал. Упаковщик не нашел зависимость, которая подгружается динамически. Добавьте ее флагом --hidden-import <имя_модуля>.
  • exe собран под другую ОС. Windows-exe не запустится на macOS или Linux и наоборот. Собирайте под ту систему, где будете запускать.

Выводы

  • Почти любая «компиляция py в exe» на деле упаковка (freezing): внутри exe лежит байткод и интерпретатор, которые распаковываются и исполняются на запуске, а не машинный код.
  • PyInstaller — основной путь: pip install pyinstaller, --onefile собирает единственный exe в папке dist; кросс-компиляции нет, файл собирается только под ту ОС, где запущена сборка.
  • auto-py-to-exe — это графическая надстройка над PyInstaller, а не отдельный компилятор: те же флаги, только мышкой.
  • Настоящую компиляцию в машинный код делает только Nuitka (Python -> C -> нативный файл): быстрее на вычислениях и лучше скрывает исходник, но сборка дольше и нужен компилятор C.
  • Типовые сбои решаются по симптому: ресурсы в --onefile ищут через sys._MEIPASS, динамические зависимости добавляют флагом --hidden-import, а exe запускают на той же ОС, под которую он собран.

Где применяется и что учить дальше

Сборка в exe нужна, когда программу на Python отдают людям без установленного интерпретатора: небольшие утилиты, десктопные инструменты с графическим интерфейсом, внутренние скрипты для коллег. На практике это связка из трех навыков: писать переносимый код, разбираться в зависимостях проекта и настраивать сборку под целевую ОС.

Освойте тему на практике

Если хочется освоить Python до уровня, где упаковка и деплой — рутинная часть работы, а не квест, посмотрите специализацию Python-разработчика в Otus. Оценить формат и уровень до старта помогают бесплатные открытые уроки Otus — живые занятия с преподавателями.

FAQ

Можно ли собрать Windows-exe на macOS или Linux? Одной командой — нет. PyInstaller, cx_Freeze и Nuitka не умеют кросс-компиляцию и собирают файл только под текущую ОС. Для Windows-exe используют Windows: отдельную машину, виртуалку или Windows-раннер в CI.

Почему exe получается таким большим (десятки мегабайт)? Потому что внутрь кладется весь интерпретатор Python и подтянутые библиотеки. Уменьшить размер помогают виртуальное окружение только с нужными пакетами и утилита UPX для сжатия исполняемого файла.

Скрывает ли exe мой исходный код? У упаковщиков (PyInstaller и подобных) — слабо: внутри лежит байткод, который поддается обратному разбору. Если защита кода важна, берите Nuitka — после компиляции в машинный код восстановить исходник заметно сложнее.

OTUS Журнал
Скидка 5% 12-19 октября на курсы (popup)
Бесплатные открытые уроки (поп-ап)