使用pyinstaller将pyqt5打包为MacOS App

官方文档

https://pyinstaller.readthedocs.io/en/stable/usage.html

TL;DR

1
2
3
4
cd yourprogram
sudo pyi-makespec --onefile --windowed yourscript.py
#如果你修改了py文件,也不用再运行一遍👆的代码
sudo pyinstaller --clean --noconfirm yourscript.spec

出现no permission问题,用sudo就对了。

我的环境:

163 INFO: PyInstaller: 3.6
164 INFO: Python: 3.7.4
187 INFO: Platform: Darwin-19.2.0-x86_64-i386-64bit
219 INFO: UPX is available.

代码

基本格式:

pyinstaller options.. myscript.py

pyinstaller --windowed --onefile --clean --noconfirm testqt.py

这样生成的文件夹dist中是pkg文件,往往打开就出错,不知为何

通过上面的代码,根目录下还会生成一个spec文件,spec文件是告诉pyinstaller如何打包你的程序的配置文件,对spec文件做相同的操作,就可以获得app文件。

pyinstaller options.. myscript.spec

pyinstaller --clean --noconfirm testqt.spec

怎么直接获得spec文件呢?

pyi-makespec options *name*.py

spec文件打开后应该能看到类似这样的字样

1
2
3
4
app = BUNDLE(exe,
name='myscript.app',
icon=None,
bundle_identifier=None)

options

注意短横-后是缩写,–后是全称。

https://pyinstaller.readthedocs.io/en/stable/usage.html

对py的pyinstaller 和pyi-makespec命令(只列出常用)

  • –clean
    • Clean PyInstaller cache and remove temporary files before building.
  • –noconfirm -y
    • Replace output directory (default: SPECPATH/dist/SPECNAME) without asking for confirmation
  • –windowed -w
    • Windows and Mac OS X: do not provide a console window for standard i/o. On Mac OS X this also triggers building an OS X .app bundle. On Windows this option will be set if the first script is a ‘.pyw’ file. This option is ignored in *NIX systems.
  • –onefile -F
    • Create a one-file bundled executable.
  • onedir -D
    • Create a one-folder bundle containing an executable (default)
  • –osx-bundle-identifier BUNDLE_IDENTIFIER
    • Mac OS X .app bundle identifier is used as the default unique program name for code signing purposes. The usual form is a hierarchical name in reverse DNS notation. For example: com.mycompany.department.appname (default: first script’s basename)

官方说对于对py的pyinstaller选项库和pyi-makespec的选项库是一样的。

You create a spec file using this command:

pyi-makespec options *name*.py [other scripts …]

The options are the same options documented above for the pyinstaller command. This command creates the *name*.spec file but does not go on to build the executable.

然而其实不是的,如果你加入 –clean的选项,则会出现pyi-makespec: error: unrecognized arguments: --clean,经过测试–noconfirm也是不能用的。

对spec的pyinstaller

对于spec文件操作,只有这些命令是起作用的。

  • --upx-dir=
  • --distpath=
  • --workpath=
  • --noconfirm
  • --ascii
  • --clean

高分辨率app

当你好不容易打包好一个app后问题又来了,你发现你的app的ui异常模糊,分辨率很低。你只需要在spec文件中加上info_plist就能解决问题。

1
2
3
4
5
6
7
8
app = BUNDLE(exe,
name='myscript.app',
icon=None,
bundle_identifier=None
info_plist={
'NSHighResolutionCapable': 'True' #<------这一句
},
)

减小app体积

写python程序的过程中尽量不要使用import,而是用from…import…来减少调用。

第一步:安装upx

  • 使用brew install upx

第二部:使用pipenv的干净环境进行打包操作。

  • 以下是一个本人的通用流程。依次在bash中运行。
1
2
3
4
5
6
7
8
pip install pipenv
pip install pipreqs
pipreqs #generate clean requirements.txt
pipenv install
pipenv shell
pip install -r requirements.txt
pyi-makespec --onefile --windowed myscript.py
pyinstaller --noconfirm --clean myscript.spec

不知道问题出在哪里怎么办?

运行dist文件夹下的同名unix进程,该进程会在terminal中打开,如果有错误会在terminal中表现出来。

比如我的app一开始只要双击就会闪退,于是我使用这个方法,控制台中出现了如下错误。经过搜索了解到是setuptools最新的几个版本和pyqt5有点冲突。使用pip install setuptools==44.0.0安装44版本后就没问题了。

File “site-packages/pkg_resources/init.py”, line 86, in

ModuleNotFoundError: No module named ‘pkg_resources.py2_warn’