Причиной написания статьи, явилось огромное количество постоянно возникающих у новичков вопросов такого содержания: "Как собрать проект c pyqt5", "Почему не работает", "Какой инструмент выбрать" и т.д. Сегодня научимся собирать проекты без мучений и танцев с бубном.



Как-то пришлось написать небольшое desktop-приложение. В качестве языка программирования для разработки был выбран python, поскольку для решения моей задачи он подходил идеально. В стандартную библиотеку Python уже входит библиотека tkinter, позволяющая создавать GUI. Но проблема tkinter в том, что данной библиотеке посвящено мало внимания, и найти в интернете курс, книгу или FAQ по ней довольно-таки сложно. Поэтому было решено использовать более мощную, современную и функциональную библиотеку Qt, которая имеет привязки к языку программирования python в виде библиотеки PyQT5. Более подробно про PyQT можете почитать здесь. В качестве примера я буду использовать код:


#!/usr/bin/python3
# -*- coding: utf-8 -*-

import sys
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtGui import QIcon

class Example(QWidget):

    def __init__(self):
        super().__init__()

        self.initUI()

    def initUI(self):

        self.setGeometry(300, 300, 300, 220)
        self.setWindowTitle('Icon')
        self.setWindowIcon(QIcon('web.png'))

        self.show()

if __name__ == '__main__':

    app = QApplication(sys.argv)
    ex = Example()
    sys.exit(app.exec_())

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


Существует большое количество библиотек, позволяющих это сделать, среди которых самые популярные: cx_Freeze, py2exe, nuitka, PyInstaller и др. Про каждую написано довольно много. Но надо сказать, что многие из этих решений позволяют запускать код только на компьютере, с предустановленным интерпретатором и pyqt5. Не думаю, что пользователь будет заморачиваться и ставить себе дополнительные пакеты и программы. Надеюсь, вы понимаете, что запуск программы на dev-среде и у пользователя это не одно и тоже. Также нужно отметить, что у каждого решения были свои проблемы: один не запускался, другой собирал то, что не смог потом запустить, третий вообще отказывался что-либо делать.


После долгих танцев с бубном и активным гуглением, мне все же удалось собрать проект с помощью pyinstaller, в полностью работоспособное приложение.


Немного о Pyinstaller


Pyinstaller собирает python-приложение и все зависимости в один пакет. Пользователь может запускать приложение без установки интерпретатора python или каких-либо модулей. Pyinstaller поддерживает python 2.7 и python 3.3+ и такие библиотеки как: numpy, PyQt, Django, wxPython и другие.


Pyinstaller тестировался на Windows, Mac OS X и Linux. Как бы там ни было, это не кросс-платформенный компилятор: чтобы сделать приложение под Windows, делай это на Windows; Чтобы сделать приложение под Linux, делай это на Linux и т.д.


PyInstaller успешно используется с AIX, Solaris и FreeBSD, но тестирование не проводилось.


Подробнее о PyInstaller можно почитать здесь: документация.


К тому же после сборки приложение весило всего около 15 мб. Это к слову и является преимуществом pyinstaller, поскольку он не собирает все подряд, а только необходимое. Аналогичные же библиотеки выдавали результат за 200-300 мб.


Приступаем к сборке


Прежде чем приступить к сборке мы должны установить необходимые библиотеки, а именно pywin32 и собственно pyinstaller:


pip install pypiwin32
pip install pyinstaller

Чтобы убедится, что все нормально установилось, вводим команду:


pyinstaller --version

должна высветиться версия pyinstaller. Если все правильно установилось, идем дальше.


В папке с проектом запускаем cmd и набираем:


 pyinstaller myscript.py

Собственно это и есть простейшая команда, которая соберет наш проект.
Синтаксис команды pyinstaller таков:


pyinstaller [options] script [script ...] | specfile


Наиболее часто используемые опции:


--onefile — сборка в один файл, т.е. файлы .dll не пишутся.
--windowed -при запуске приложения, будет появляться консоль.
--noconsole — при запуске приложения, консоль появляться не будет.
--icon=app.ico — добавляем иконку в окно.
--paths — возможность вручную прописать путь к необходимым файлам, если pyinstaller
не может их найти(например: --paths D:\python35\Lib\site-packages\PyQt5\Qt\bin)


PyInstaller анализирует файл myscript.py и делает следующее:


  1. Пишет файл myscript.spec в той же папке, где находится скрипт.
  2. Создает папку build в той же папке, где находится скрипт.
  3. Записывает некоторые логи и рабочие файлы в папку build.
  4. Создает папку dist в той же папке, где находится скрипт.
  5. Пишет исполняемый файл в папку dist.

В итоге наша команда будет выглядеть так:


pyinstaller --onefile --icon=name.ico --noconsole myscript.py

После работы программы вы найдете две папки: dist и build. Собственно в папке dist и находится наше приложение. Впоследствии папку build можно спокойно удалить, она не влияет на работоспособность приложения.


Спасибо за внимание. Надеюсь статья была вам полезна.

Поделиться с друзьями
-->

Комментарии (16)


  1. prostofilya
    04.04.2017 14:41

    У меня самая большая боль случилась с установкой пакетов и пайинсталлера в том числе, у меня то один пакет не работал, то другой, то проект просто не запускался. А проблема решилась просто установкой питона в корень диска.
    По умолчанию питон на винде просится в Program files, но потом сам ломается об пробелы в пути.
    Правило номер 1: не ставьте питон в програм файлс.
    Ну и ещё такая штука, часто питонисты используют numpy, scipy, так вот, их желательно ставить отсюда.


  1. kuznetsovin
    04.04.2017 15:23

    Когда я неделю назад пытался собрать такой же проект pyinstaller c python3.6 не работал. Кроме того были проблемы с запуском на чистой машине без установленного QT, когда собирается один файл и запускается потом, причем такого не наблюдалось с PyQt4.


    1. prostofilya
      04.04.2017 16:10

      pyinstaller пока ещё не собран под 3.6, следить можно на офсайте


      1. kuznetsovin
        04.04.2017 16:12

        Кроме того были проблемы с запуском на чистой машине без установленного QT
        — это проблема не зависит от версии python.


      1. delvin-fil
        04.04.2017 17:49

        Собран.

        pyinstaller templ2.py
        417 INFO: PyInstaller: 3.2.1
        418 INFO: Python: 3.6.0
        419 INFO: Platform: Linux-4.4.4-x86_64-Intel-R-_Core-TM-_i3_CPU_530_@_2.93GHz-with-gentoo-2.3
        ......
        

        Нормально установилось вчера
        $ pip3.6 install pyinstaller
        

        работает.


        1. prostofilya
          04.04.2017 18:03

          Оно устанавливается, но работает не полноценно, это не под 3.6, тут [pypi] тоже пишут что pyinstaller 3.2.1 для питона 3.3-3.5, на гитхабе в issues авторы советуют следить за офсайтом.
          Судя по всему вот процесс разработки новой версии https://github.com/pyinstaller/pyinstaller/milestone/16
          PyQt проекты собираются? Я не смог собрать под виндой 3.6 неделю назад, под 3.5 всё замечательно.


          1. delvin-fil
            04.04.2017 18:29

            Нет, с PyQt5 не собрался. Проверил сейчас.

            $ pyinstaller -p /usr/lib/python3.6/site-packages/PyQt5/ qt/qt.py3
            102 INFO: PyInstaller: 3.2.1
            103 INFO: Python: 3.6.0
            105 INFO: Platform: Linux-4.4.4-x86_64-Intel-R-_Core-TM-_i3_CPU_530_@_2.93GHz-with-gentoo-2.3
            106 INFO: wrote /home/fil/codding/qt.spec
            108 INFO: UPX is not available.
            110 INFO: Extending PYTHONPATH with paths
            ['/home/fil/codding/qt',
             '/usr/lib/python3.6/site-packages/PyQt5/',
             '/home/fil/codding']
            111 INFO: checking Analysis
            111 INFO: Building Analysis because out00-Analysis.toc is non existent
            111 INFO: Initializing module dependency graph...
            119 INFO: Initializing module graph hooks...
            121 INFO: Analyzing base_library.zip ...
            Traceback (most recent call last):
              File "/usr/bin/pyinstaller", line 11, in <module>
            ......................................................................................
            IndexError: tuple index out of range
            
            


  1. Zack
    04.04.2017 17:07

    Кстати был замечен один нюанс при сборке --onefile в *.exe под windows(тестировалось на 7). Если используется python 3.5+, то для запуска созданного *.exe на другой виндовой машине потребуется установленный vc++ redist(той версии что используется питоном), на python 3.4 такой потребности не наблюдается.


    1. splav_asv
      04.04.2017 18:30

      1. Zack
        05.04.2017 08:54

        На машине, на которой запускался *.exe не был установлен vc++ и в зависимости от того на какой версии python собирался exe требовалась его установка или нет. Обсуждение этой темы есть здесь


  1. tehmoose
    04.04.2017 18:28

    Почему не pyqtdeploy?


    1. entw
      05.04.2017 16:01

      Когда последний раз смотрел, он был из рук вон плохо документирован. Нет желания наваять статью?


      1. tehmoose
        05.04.2017 20:24

        осталось подумать, на что сделать упор, хех


  1. entw
    05.04.2017 16:05

    Год назад pyInstaller у меня не захотел работать с питоном из *.exe установщика. Только с MSI удалось завести. Починили?


  1. doctor_petrovich
    06.04.2017 18:47

    Спасибо за статью. Недавно собирал приложение (python3 PyQT5) с помощью cx_Freeze. Ваше решение кстати.
    Наверное извините за глупый вопрос, но приложение будет работать на Windows XP?


    1. FUNNYDMAN
      06.04.2017 18:48

      Сложно ответить. «Поддержка Windows XP корпорацией Microsoft прекращена 8 апреля 2014.»