pyinstaller打包py程序

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)

 

参考:

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

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top