Сложности сборки Python3 + Qt5 приложений под Windows

от автора

Недавно потребовалось мне сделать небольшую прогу под Windows. Раньше мне не доводилось разрабатывать под нее.
Сама программа несложная, написалась относительно быстро. Намного больше времени отъела сборка ее под винду. Понятно, что выбранные инструменты (Python3 + Qt5) не родные, а универстальные, но что потребуется столько времени затратить на сборку, я не предполагал.
Соответственно, хочется поделиться практикой, может кому еще придется стучаться лбом в эту стену.
Под катом выстраданная инструкция как легко собирать PyQt5 приложения в single-file.exe не требующий инсталлятора.

Наиболее известные решения для моей задачи — сборки python приложений в .exe это: py2exe, cx_freeze и pyinstaller. Про каждый написано много всего. Но очень часто авторы грешат халтурой — легко и быстро собирается программа и запускается… на том же самом компьютере. Надо ли говорить, что это две большие разницы — запуск на дев-среде и у пользователя? У меня-то и так заработает безо всяких сборок и танцев с бубном. Кроме того — кто из пользователей будет ставить себе Qt?

Для каждого инструмента есть туториал. Но у каждого были свои проблемы: один не запускался (pyinstaller до сих пор поддерживает 3-й питон в экспериментальном режиме), другой собрал то, что не смог запустить, третий вообще долгое время ничего не собирал, ругая все вокруг.
После долгой борьбы был выбран py2exe.

Секрет успеха в правильной установке компонент из правильных источников (я не даю прямые ссылки, т.к. они все равно устареют, пишу что где искать):

  • Win XP 32-bit (или другая, которую вы возьмете за базу — я специально взял самую старую систему)
  • Python 3.4 — устанавливаем с www.python.ord/download Windows x86 msi installer. Можно сразу добавить C:\Python34\ в %PATH%
  • PyWin32 — ставим с sf.net файл pywin32-219.win32.py3.4.exe
  • Qt5.5 — ставим с официального сайта qt.io. Одновременно с ним ставится компилятор mingw4.9.2
  • После установки добавляем C:\Qt\Tools\mingw492_32\bin в %PATH%.
  • Git for Windows — он нам нужен в любом случае, ставим с git-scm.com
  • PyQt5 — качаем и ставим riverbankcomputing.co.uk win32 x86 installer
  • SIP — я так и не понял почему, но тот же самый riverbankcomputing.co.uk не удосужился собрать служебный модулек, поэтому качаем win сорцы, распаковываем, дальше удобно продолжить работу в консоли Git Bash:
  • python configure.py -p win32-g++
  • mingw32-make.exe
  • mingw32-make.exe install.
  • Само собой, инсталляция не сработает (. К счастью, нам нужно поставить всего 3 файла. Идем руками в подпапку sipgen/ folder и копируем sip.exe в C:\Python34.
  • Затем иде в ../siplib и
  • copy sip.pyd c:\python34\Lib\site-packages
  • strip /c/Python34/Lib/site-packages/sip.pyd
  • наконец, копируем .h-файл:
  • cp sip.h /c/Python34/include/
  • py2exe — ставим родным способом: python -m pip install py2exe
  • pyreadline — так же: python -m pip install pyinstaller
  • 7-Zip — c сайта 7-zip.org качаем x86 exe
  • 7-zip extra — полезные дополнения качаем оттуда же, распаковываем в папку с установленным 7-zip folder. На конфликты txt-файлов можно забить.
  • Resource Hacker — качаем angusj.com — впрочем, если вы не собираетесь заменять дефолтную пиктограмму программы на свою, то она вам не потребуется. Либо ее можно заменить на windres, которая идет в комплекте с mingw — но у меня уже было сделано с RH.

Делюсь своим setup.py:

from distutils.core import setup import os, sys import py2exe from glob import glob import PyQt5  NAME="Proga"  qt_platform_plugins = [("platforms", glob(PyQt5.__path__[0] + r'\plugins\platforms\*.*'))] data_files.extend(qt_platform_plugins) msvc_dlls = [('.', glob(r'C:\Windows\System32\msvc?100.dll'))] data_files.extend(msvc_dlls) # print(data_files)  sys.argv.append('py2exe')  setup( 	data_files=data_files, 	windows=[ 		{ 			"script": "pyftp1.py", 			"icon_resources": [(0, "resources/favicon.ico")] 		} 	], 	# zipfile=None, 	options={ 		"py2exe": { 			"includes":["sip", "atexit",],  # даже если мы нигде не используем atexit его надо добавить, sip указываем явно - сборщики часто про него забывают  			# "packages": ['PyQt5'], 			"compressed": True, 			"dist_dir": "dist/" + NAME, 			# "bundle_files": 0, # не сработало ( с этой опцией на выходе прога не может найти msvc*.dll  			# "zipfile": None, # тоже лишнее 			"optimize": 2, 		} 	} ) 

Это программа-минимум. Теперь можно собирать само приложение:

python setup.py py2exe 

На выходе получаем папку с готовой прогой в dist.
Это хорошо, но не всегда удобно для пользователей. На эту папку можно натравить создаватель инсталляторов, типа Inno Setup и получить msi. В моем случае, надо было обеспечить работоспособность программы с минимальными правами пользователей — точно без права установки либ.

Поэтому я пошел дальше и запаковал в 1 файл с помощью 7-zip. Схема такая: создаем 7z-архив и к нему пристыковывается специальная SFX-голова и конфиг. Голова распаковывает архив во временную папку, смотрит в конфиг и запускает нужный exe-файл. Собирается примерно так:
cat 7zS.sfx resources/config.txt Proga.7z > Proga.exe

В файле конфига можно указать разные опции, я задал минимум:

;!@Install@!UTF-8! Title="Proga" RunProgram="Proga\\pyftp1.exe" ;!@InstallEnd@! 

Единственный недостаток — некрасивая картинка у exe файла — стандартный распаковщик. Тут-то и подменяем ему картинку на нужную нам:
RESHACKER.exe -addoverwrite Proga.exe, Proga.exe, resources/favicon.ico, ICONGROUP, MAINICON, 0

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

# start settings DIST=dist # change NAME also in setup.py and resource/config.txt NAME=Proga EXT=exe  # final name and location of the built program FINAL=$(DIST)/$(NAME).$(EXT)  # external programs 7ZIPDIR="C:\Program Files\7-Zip" RESHACKER="/c/Program\ Files/Resource\ Hacker/ResourceHacker.exe"  # intermediate steps  # no icon version of program  NOICON=$(DIST)/$(NAME)_no_icon.$(EXT)  # name of .7z archive 7Z_BASENAME=$(NAME).7z 7Z=$(DIST)/$(7Z_BASENAME)  # folder with ready .exe PROGDIR=$(DIST)/$(NAME)  all: $(FINAL)   $(FINAL): $(NOICON) 	# change icon 	"$(RESHACKER)" -addoverwrite $(NOICON), $(FINAL), resources/favicon.ico, ICONGROUP, MAINICON, 0   $(NOICON): $(7Z) 	#build autorunning sfx with default icon 	cat $(7ZIPDIR)/7zS.sfx resources/config.txt $(7Z) > $(NOICON)   $(7Z): exe 	# compress program folder to .7z 	cd $(DIST);  $(7ZIPDIR)\\\7z.exe a  $(7Z_BASENAME)  $(NAME)   exe:  $(DIST) 	# build program itself 	python setup.py py2exe   $(DIST):  	# create dist directory  	# echo $(DIST)/   clean: 	rm -rf $(DIST)/*  

Теперь можно очень легко пересобирать прогу:

mingw492-make.exe clean all 

Успехов в сборке!
Расскажите про свой опыт!

ссылка на оригинал статьи http://habrahabr.ru/post/264233/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *