logo头像

pyinstaller打包exe

参考:

  1. 官网
  2. pyinstaller参数使用
  3. 使用spec文件

安装

Windows依赖pypiwin32,新版的pyinstaller已经包含了该模块,不用单独安装。

1
pipenv install pyinstaller

运行

1
pyinstaller [options] xxx.py

运行

完整的命令行:

1
pyinstaller [options] script [script …] | specfile

最简单的调用方式

1
pyinstaller myscript.py

常用参数

1
2
3
4
5
6
-F	指定打包后只生成一个exe格式的文件
-D –onedir 创建一个目录,包含exe文件,但会依赖很多文件(默认选项)
-c –console, –nowindowed 显示控制台界面(默认)
-w –windowed, –noconsole 使用窗口,无控制台
-p 添加搜索路径,让其找到对应的库
-i 改变生成程序的icon图标

更详细的使用方法可以参考下载包里的doc目录下的Manual.html文件。

注意事项:
生成文件中,可能包含一个以warn开头的类似warndemo.txt的警告文件,是因为程序无法自动导入很多的库,使用-p参数添加搜索路径。

使用spec文件

如果不想每次都传入参数,可以使用配置文件spec。
首先创建spec文件:

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

options和从命令行传入的options是相同的。这里传入的option会自动填入spec文件对应的位置,也可以不传入options直接填写spec文件。

使用spec文件,运行时无需指定py直接指定spec文件:

1
pyinstaller myscript.spec

注意:以上如果指定了options会被忽略并使用spec中的值。如,使用了spec之前又指定了-c,spec会一直保留配置

1
2
3
exe = EXE(pyz,
...
console=True,

后面再使用spec指定命令行的-c就没有用了,则要修改spec中的console=True来显示控制台。

从spec文件创建时,只有以下命令行参数有效:

1
2
3
4
5
6
--upx-dir=
--distpath=
--workpath=
--noconfirm
--ascii
--clean

spec文件详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
block_cipher = None
a = Analysis(['minimal.py'],
pathex=['/Developer/PItests/minimal'],
binaries=None,
datas=None,
hiddenimports=[],
hookspath=None,
runtime_hooks=None,
excludes=None,
cipher=block_cipher)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,... )
coll = COLLECT(...)

有四个类实例:

  1. Analysis实例a:该项配置脚本名称,解析导入和依赖包
  2. PYZ
  3. EXE
  4. COLLECT
    修改 spec文件将参数写到Analysis和EXE.

添加datas,-h帮助描述如下

1
[--add-data <SRC;DEST or SRC:DEST>]

windows上要使用分号,linux上要使用冒号。

是否使用分号或冒号分隔符取决于os.pathsep.
windows下,打开cmd,输入
import os
os.pathsep
输出的是分号’;’。

注意:如果在Windows上使用了冒号,会报错:

1
argument --add-data: invalid add_data_or_binary value

使用add-data参数时会加入到spec文件的datas中(也可以直接写到spec中),如

1
--add-data="assets/bg.jpg;assets"

spec

1
datas=[('assets/bg.png', 'assets')],

修改exe图标

1
pyinstaller -F -i some.ico demo.py

需要注意:需要移动下生成可执行程序的位置,才可以显示图片。

-i添加到了spec的exe实例中的icon参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
runtime_tmpdir=None,
console=False ,
icon='assets\\icon.ico')

生成

  1. dist文件夹(包含生成好的.exe)
  2. build文件夹(中间生成,没用,事后可以删掉)
  3. spec文件(要转换文件的同一目录下,用于生成exe文件,可以修改来自定义生成exe的属性)

不压缩生成的exe文件

不压缩打包的时候记得把所有的静态文件复制过去,包括icon和background。

issues

注意:到步骤Looking for dynamic libraries
的时候超级慢,等了大概20分钟才继续下面的步骤。未找到加快的解决方法。

运行打包好后的exe报错:

1
failed to execute script

重新打包,去掉-w参数,看console输入的错误后,调试。

main.b is not a package

1
python: __main__.b is not a package

这个x是模块名称,查看使用了相对导入,如from .a import b.找到了一个相对清楚的解释.

修改为from c.a import b, c为a的包名,再重新生成后OK。

图片资源没打包进去

试了下,代码中写的image必须使用绝对路径打包完才能显示出来。

使用官方小实例

下载Windows版本,解压后在根目录下的examples有很多官方的小实例