Skip to content

Latest commit

 

History

History
204 lines (112 loc) · 11.4 KB

create_executable_file.md

File metadata and controls

204 lines (112 loc) · 11.4 KB

Инструкция по созданию исполняемого файла (Win, Linux) с помощью утилиты PyInstaller

Создание exe файла с помощью PyInstaller

PyInstaller собирает в один пакет Python-приложение и все необходимые ему библиотеки следующим образом:

  • считывает файл скрипта

  • анализирует код для выявления всех зависимостей, необходимых для работы

  • создает файл spec, который содержит название скрипта, библиотеки-зависимости, любые файлы, включая те параметры, которые были переданы в команду PyInstaller

  • собирает копии всех библиотек и файлов вместе с активным интерпретатором Python

  • создает папку BUILD в папке со скриптом и записывает логи вместе с рабочими файлами в BUILD

  • создает папку DIST в папке со скриптом, если она еще не существует

  • записывает все необходимые файлы вместе со скриптом или в одну папку, или в один исполняемый файл

  1. для установки утилиты PyInstaller следует находясь в виртуальном окружении выполнить команду: pip install pyinstaller

  2. проверить установленную версию PyInstaller можно командой:

    pyinstaller --version

  3. непосредственно для создания исполняемого файла в командной строке выполняется команда:

    pyinstaller --onefile start_constructor.py

    Примечание:

    • если используется параметр --onedir или -D при генерации исполняемого файла, тогда исполняемый файл и зависимые данные с библиотеками будут помещены в одну папку (это поведение по умолчанию);
    • если же использовать параметр --onefile или -F, то всё окажется в одном исполняемом файле, то PyInstaller распаковывает все файлы в папку TEMP, выполняет скрипт и удаляет TEMP (Как скомпилировать python-скрипт в exe-файл)

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

    ​ После завершения установки в рабочей директории появятся две папки:

    BUILD и DIST, а также новый файл с расширением .spec

    Название spec-файла будет таким же, как и наименование файла скрипта.

    Файл spec

    ​ Файл spec — это первый файл, который PyInstaller создает, чтобы закодировать содержимое скрипта Python вместе с передаваемыми при запуске параметрами.

    PyInstaller считывает содержимое файла для создания исполняемого файла, определяя всё, что может понадобиться для его запуска.

    Файл с расширением .spec по умолчанию сохраняется в текущей директории.

  4. дополнительные импорты с помощью Hidden Imports

​ Исполняемому файлу требуются все импорты, которые нужны python-скрипту. Иногда PyInstaller может пропустить динамические импорты или импорты второго уровня, возвращая ошибку ImportError: No module named

​ Для разрешения этой ошибки необходимо передать название недостающей библиотеки в hidden-import

Например, чтобы добавить библиотеку 'os', в командной строке следует написать команду:

pyinstaller --onefile --hidden-import "os" simple1.py

В нашем случае для правильной сборки исполняемого файла start_constructor также потребовалось использовать опцию 'hidden-import'

Алгоритм:

  • в результате выполнения команды

    pyinstaller --onefile start_constructor.py

    создаётся файл start_constructor.spec

  • содержимое папок BUILD и DIST необходимо удалить

  • отредактировать файл start_constructor.spec, добавив строки

    pathex=[
    '.',
    ],
    binaries=[],
    datas=[],
    hiddenimports=['desktop_constructor_app'],
    

    где атрибут pathex отвечает за путь к папке проекта и значение '.' определяет рабочую директорию для сборки исполняемого файла ('tg_bot_constructor'),

    ​ а 'desktop_constructor_app' - импортируемый через опцию hidden-import модуль

  • после редактирования содержимого файла start_constructor.spec выполняется новая сборка исполняемого файла командой:

    pyinstaller start_constructor.spec

    ​ Примечание: файл start_constructor.spec можно также получить не выполняя сборку с помощью команды pyi-makespec start_constructor.spec, в результате выполнения которой создается spec-файл по умолчанию, содержащий все параметры, которые можно указать в командной строке; файл start_constructor.spec создается в текущей директории

  1. все требуемые для работы исполняемого файла данные возможно собрать в один бандл с помощью параметра --add-data

    a = Analysis(
        ['start_constructor.py'],
        pathex=[
    	'.',
    	],
    	binaries=[],
    	datas=[(
        	Path('desktop_constructor_app') / 'constructor_app' / 'translations' / '*.qm',
    	    Path('desktop_constructor_app') / 'constructor_app' / 'translations'
    	)],
    	hiddenimports=['desktop_constructor_app'],
    

    Здесь в качестве первого атрибута для объекта класса Analysis передается имя py-файла, который необходимо скомпилировать.

    В списке datas указываются файлы, которые требуется загрузить для работы приложения (изображения, музыка/звуки, шрифты).

    datas — это список кортежей;

    каждый кортеж имеет два элемента строкового типа:

    • 1-й — путь до файла, который необходимо загрузить

    • 2-й указывает имя папки для хранения файла во время выполнения программы

      Примечание: если использовать в виде

      a = Analysis(['start_constructor.py'],
                   pathex=['C:/Users/1/Desktop/Python/test'],
                   binaries=[],
                   datas=[('Images/image.png', 'Images'), 
                   ('Music/track.mp3', 'Music'), 
                   ('font.ttf', '.')],
                   hiddenimports=[],
      

      ('.' — означает, что файл будет помещен во временную папку без подкаталога)

    Если использовать импортирование

    from pathlib import Path,

    то использование Path( ) в записи datas позволит унифицировать задание путей для применения с Windows и Linux

    В экземпляре класса EXE редактируется: name — имя exe-файла console — отвечает за то, будет ли вызываться консоль при запуске приложения (True) или нет (False) icon — содержит путь к иконке игры

    Разъяснения по редактированию путей к файлам в коде

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

    def resource_path(relative):
        if hasattr(sys, "_MEIPASS"):
            return os.path.join(sys._MEIPASS, relative)
        return os.path.join(relative)
    

    При запуске приложения PyInstaller распаковывает данные во временную папку и сохраняет путь к ней в переменной среды _MEIPASS.

    Функция resource_path проверяет, создана ли временная папка, и если да, то возвращает путь к ней для дальнейшей загрузки файлов. В противном случае (например, если запустить код через интерпретатор) функция вернет тот путь, который в неё передали (то есть путь к папке проекта с программой).

    Чтобы получить путь к файлу

    • если файл лежит в той же папке, что и py-файл:
    path = resource_path('image.png')
    
    • если файл вынесен в отдельную папку проекта:
    path = resource_path(os.path.join('Folder', 'image.png'))
    

    При этом, если файл вынесен в отдельную папку проекта, то и во временной папке нужно создавать соответствующий подкаталог

    (см. редактирование параметра datas)

    Далее загружаем файл:

    img = pygame.image.load(path)
    

    С музыкой и шрифтами аналогично.