1. 基本语法
pyinstaller命令行的语法是:
pyinstaller [options] script [script …] | specfile
通常情况只需要将命令行移动到需要打包的脚本根目录下,然后运行:
# 打包myscript.py脚本,生成一个包含可执行文件的目录 pyinstaller myscript.py # 打包myscript.py脚本,生成单个可执行文件,并且关闭终端输出 pyinstaller --onefile --windowed myscript.py
pyinstaller会分析myscript.py脚本,并且:
- 生成myscript.spec文件
- 生成build目录,里面包含解析日志以及临时文件
- 生成dist目录,里面包含最终输出的可执行文件(目录)
2. 常用参数
-D, –onedir | (默认)打包成一个包含可执行文件的目录 |
-F, –onefile | 打包成单个可执行文件 |
-n NAME, –name NAME | 定义输出的spec文件名以及打包后的程序文件名(默认为第一个script实参的文件名) |
–add-data <SRC;DEST or SRC:DEST> | 追加其他非.py文件,通常写在spec文件里面 |
–key KEY | 使用KEY参数加密pyc文件 |
-c, –console, –nowindowed | (默认)打开终端窗口 |
-w, –windowed, –noconsole | 不打开终端窗口 |
-i FILE.ico, –icon FILE.ico | 可执行文件的图标(注意.ico文件需要包含多种分辨率的图标,缺少的会自动使用pyinstaller图标) |
3. spec文件用法
有些情况下,我们会需要修改spec文件,来生成完整的程序包。
- 需要打包资源文件(pyinstaller默认只会打包.py文件)
- 需要打包一些pyinstaller无法找到的动态库
- 为可执行程序添加运行时参数
- 打包多个程序
3.1 生成 spec 文件
生成spec文件的语法:
pyi-makespec options script_name.py [other scripts]
这会在当前目录下生成 script_name.spec 文件。
通常我更喜欢用 pyi-makespec -n app_name myscript.py
,指定要生成的 spec 文件名为 app_name.spec,亦指定最终打包成的程序名为 app_name。
修改 spec 文件,然后通过 pyinstaller script_name.spec
进行打包。
3.2 修改 spec 文件
spec 文件中实际上是定义了四个类实例:Analysis,PYZ,EXE,COLLECT。以下图为例:
与目录解析相关的参数添加在 Analysis 实例中,与最终 exe 文件相关的参数添加在 EXE 实例中。
Anaylsis.pathex 参数是一个列表,它指示除了系统环境变量外,还可以去哪里查找 import 用到的库。默认就是当前程序目录。
Analysis.datas 参数表示要追加的文件或目录,该参数是一个二元组列表。每个二元组表示 (源文件路径, 打包后目标路径)
。
Anaylsis.binaries 参数表示要追加的非 python 库。比如:binaries=[('/usr/lib/libiodbc.2.dylib', './vendor/')],
表示将 libiodbc.2.dylib 文件打包到最终的 vendor 目录下。
EXE.console 参数表示是否开启终端窗口。
EXE.icon 参数表示程序图标。
EXE.version 参数表示最终生成的 .exe 文件的版本信息(右键点击生成的 .exe 文件 – 属性 – 详细信息)。嫌麻烦可忽略改参数。
4. 添加版本信息
windows
先用pyinstaller自带的pyi-grab_version命令从已有的windows程序中获取一份版本信息样本文件。
然后修改成自己的版本信息。最后在打包的时候添加参数–version-file version_info.txt,或者写入spec文件中来打包。
macOS
5. 打包后程序运行失败怎么办?
程序编码时运行正常,打包后在本机运行正常,但是copy到别的电脑却无法运行,弹出错误窗口:“failed to execute script main”。我这次遇到的情况是打包后程序在别的电脑也能正常运行,但是加入windows启动运行后,每次系统自动启动的程序都是弹出运行错误无法启动,手工运行又是正常的。有什么办法能检查错误信息呢?
首先是打包的时候将终端窗口打开,但是由于程序是在启动时出错,所以这个dos窗口也直接闪退了,根本来不及看错误信息。想了想,应该在try…catch…一下main函数,把错误信息打印出来后sleep几秒,这样dos窗口就不会闪退啦。
if __name__ == '__main__': import time try: main() except Exception as e: logging.exception('错误信息:') print('出错啦啊啊啊!!!') time.sleep(60)
重新打包,加入系统启动项,检查错误信息。发现还是由于一些静态文件路径找不到的问题。
原来windows系统启动项随机启动程序时,当前路径是在C:\Windows\system32,并不是程序所在目录。=。=#
解决这个路径问题的最好办法就是直接在main函数之前就
BASE_PATH = os.path.split(os.path.realpath(sys.argv[0]))[0] os.chdir(BASE_PATH)
参考: