БэкендPython

Как сделать EXE из Python-скрипта через PyInstaller: один файл и запуск без Python

Собираем работающий EXE из файла Python на Windows: отдельное окружение, режимы onedir и onefile, имя, иконка, данные и диагностика ошибок запуска.

Кодик

Автор

5 мин чтения

Чтобы превратить Python-скрипт в EXE, собирайте его на Windows командой py -m PyInstaller --onefile app.py и забирайте готовый файл из папки dist. Начните с режима onedir, убедитесь, что программа запускается, и только потом переходите к одному файлу. PyInstaller кладёт внутрь интерпретатор и зависимости, поэтому на компьютере пользователя Python не нужен.

Обычно эта задача появляется после первого полезного скрипта: калькулятор работает из VS Code, но друг не хочет устанавливать Python и открывать терминал. EXE решает доставку, но не чинит ошибки программы. Если скрипт не запускается командой py app.py, сборка лишь упакует ту же проблему в более тяжёлый файл.

1Проверяем

Запускаем исходный .py из чистого виртуального окружения и фиксируем зависимости.

2Собираем

Сначала используем onedir для диагностики, затем добавляем --onefile.

3Тестируем

Открываем результат из dist, проверяем файлы данных и запуск на другом профиле Windows.

Что именно делает PyInstaller и где искать готовый файл

PyInstaller анализирует импорты, добавляет интерпретатор Python и нужные библиотеки, а затем создаёт автономный набор. Это упаковщик, а не компилятор исходника в машинный код. После команды рядом со скриптом появляются три объекта: служебная папка build, файл настроек .spec и результат в dist. Распространять нужно содержимое dist, а не случайный файл из build.

ОбъектЧто внутриЧто с ним делать
build/Временные файлы анализа и сборкиНе отправлять пользователю, можно пересоздать
dist/app/EXE и библиотеки режима onedirЗапускать весь каталог целиком
dist/app.exeОдин файл режима onefileОтправлять после проверки
app.specРецепт сборки, данные и скрытые импортыХранить рядом с проектом при сложной конфигурации

Схема пути Python-скрипта через анализ зависимостей к папке dist
Исходник проходит анализ, а пользователю уходит только проверенный результат из dist.

Собирайте под ту систему, где будет запуск. Windows-версия создаётся на Windows, а macOS-приложение на macOS. Готовый EXE не появляется корректно при обычной сборке на другой операционной системе.

Собираем первый EXE в отдельном окружении

Создайте папку проекта и файл hello.py. Виртуальное окружение отделит PyInstaller и библиотеки от других проектов. В PowerShell активируйте окружение, поставьте упаковщик через тот же интерпретатор и выполните сначала обычную сборку. Если команда py недоступна, используйте python в тех же строках.

# hello.py
name = input("Your name: ").strip() or "Developer"
print(f"Hello, {name}!")
input("Press Enter to close...")

# PowerShell в папке проекта
py -m venv .venv
.\.venv\Scripts\Activate.ps1
py -m pip install --upgrade pyinstaller
py -m PyInstaller hello.py

# После успешного теста
py -m PyInstaller --onefile --name HelloApp hello.py
.\dist\HelloApp.exe
Признаки успешной сборки
  • В конце журнала есть строка об успешном завершении, а в dist появился каталог или EXE.
  • При запуске программа спрашивает имя, печатает приветствие и ждёт Enter, поэтому окно не закрывается мгновенно.
  • Повторная сборка с --name HelloApp создаёт понятное имя вместо имени исходного файла.

Сравнение режимов PyInstaller onedir и onefile
Onedir проще чинить, onefile проще передавать. Начинать выгоднее с первого.

Когда выбирать onefile, onedir и windowed

Один EXE удобнее отправлять, но он распаковывает служебные файлы во временный каталог при каждом запуске. Режим onedir быстрее диагностировать: рядом видны библиотеки и ресурсы. Флаг --windowed подходит графическому приложению, но скрывает консоль вместе с сообщениями об ошибках. Не добавляйте его, пока сборка не стала стабильной.

ФлагРезультатКогда использовать
без флагаПапка onedirПервая сборка и поиск пропавших библиотек
--onefileОдин исполняемый файлНебольшая проверенная программа
--windowedБез консольного окнаTkinter, PySide или другая GUI-программа
--icon app.icoСвоя иконка WindowsФинальная версия после рабочего прототипа
--add-dataДополнительные картинки и конфигиКогда код читает файлы во время запуска
Один файл не означает маленький файл. В пакет входит интерпретатор и импортированные библиотеки. Простая программа часто весит заметно больше исходника, и это нормальная цена автономного запуска.

Практика: собираем и проверяем HelloApp

Проверка должна повторять путь будущего пользователя. Не запускайте EXE только из терминала разработчика: там уже есть переменные окружения, библиотеки и привычная рабочая папка. Скопируйте результат в отдельный каталог и откройте двойным щелчком. Затем повторите запуск из PowerShell, чтобы увидеть код возврата и сообщения.

Сборка без догадок
  1. Запустите py hello.py и проверьте два ввода: непустое имя и пустую строку.
  2. Создайте .venv, установите PyInstaller и выполните сборку без --onefile.
  3. Откройте dist/hello/hello.exe. Не переносите только EXE из папки onedir отдельно от библиотек.
  4. Если всё работает, соберите --onefile --name HelloApp и запустите новый файл.
  5. Скопируйте EXE в пустую папку вне проекта и повторите оба варианта ввода.
  6. Только после этого добавляйте иконку, данные или --windowed, по одному изменению за сборку.
Что должно получиться
  • В dist лежит HelloApp.exe, который работает без активированного окружения.
  • Пустой ввод даёт приветствие для Developer, обычный ввод возвращает указанное имя.
  • После переноса в пустую папку программа не ищет исходный hello.py.

Карта диагностики ошибок EXE по коду импортам и файлам
Симптом подсказывает уровень: код, импорт, ресурс или операционная система.

Почему EXE не запускается или теряет файлы

Если двойной щелчок ничего не показывает, откройте PowerShell, перейдите в dist и запустите EXE оттуда. Консоль сохранит traceback. Ошибки обычно относятся к одному из трёх уровней: исходный код, импорт библиотеки или путь к данным. Пересобирать десять раз одной командой бессмысленно, пока не определён уровень.

Сразу включён windowed

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

В коде жёсткий относительный путь

После упаковки рабочая папка может отличаться. Формируйте путь от __file__ или добавляйте ресурс через spec-файл.

Сборка сделана не под целевую ОС

PyInstaller не является обычным кросс-компилятором. Соберите Windows-результат на Windows нужной архитектуры.

Антивирусу отправляют каждую сырую сборку

Самодельные неподписанные EXE могут вызвать предупреждение. Не отключайте защиту, проверьте файл и объясните происхождение получателю.

Меняйте один параметр за попытку. Сначала рабочий onedir, затем onefile, потом данные и в самом конце скрытие консоли. Такой порядок оставляет понятную точку, после которой появилась ошибка. Технические детали сверены с официальной документацией PyInstaller.
Короткие ответы
Где лежит готовый EXE?

В папке dist. Каталог build содержит служебные файлы.

Нужен ли Python пользователю?

Нет. PyInstaller включает интерпретатор и зависимости в поставку.

Почему лучше начать с onedir?

В папке видны компоненты сборки, поэтому проще найти отсутствующую библиотеку или файл.

Что делает --windowed?

Скрывает консольное окно. Вместе с ним исчезает и удобный вывод ошибок.

Можно ли собрать Windows EXE на macOS?

Обычный рабочий процесс PyInstaller предполагает сборку отдельно на каждой целевой системе.

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

Потренируйте файлы, функции и обработку ошибок в курсе Python. Если среда ещё не настроена, используйте гайд по VS Code для Python или запускайте упражнения прямо в Кодике.

При ошибке импорта откройте разбор ModuleNotFoundError, а проблему с командой установки разбирает статья про pip на Windows.