Pyinstaller防坑指南

编写好的Python脚本是可通过工具转换成一个可执行文档,这样在不同的电脑上可直接运行,甚至不需要安装Python与依赖。目前感觉上最好用的是pyinstaller,但使用时有坑。

Pyinstaller防坑指南

看看官方对pyinstaller的定义:

PyInstaller reads a Python script written by you. It analyzes your code to discover every other module and library your script needs in order to execute. Then it collects copies of all those files – including the active Python interpreter! – and puts them with your script in a single folder, or optionally in a single executable file.

把Python脚本打包成可执行文档来使用,特别适合分享应用,用户可直接运行.exe的可执行文档,不需要安装Python与相应的Package,但是pyinstaller打包出来的.exe文档经常会运行出错,点击运行exe后闪退,也不知错在哪里。这时候应该怎么办?

我们打开系统自带的CMD,在CMD里运行.exe文档,错误信息会显示在CMD里,即使运行出错也不会闪退,或者可以把.exe文档拖动到CMD里面。

💡
打包时一定要确保脚本运行是没有问题,不然打包好绝对出错!

故障:No such file or directory

1.

pyinstaller在打包脚本的时候会搜索脚本所需要的依赖(libraries),但它主要是识别import语句所导入的模块,其它方式引用的Python libraries将不被识别。

Some Python scripts import modules in ways that PyInstaller cannot detect: for example, by using the __import__() function with variable data, using importlib.import_module(), or manipulating the sys.path value at run time. If your script requires files that PyInstaller does not know about, you must help it.

.exe文件运行出错缺少什么包,我们就用--collect-all手动添加包的名字,直到所有的包都添加进去:

pyinstaller --collect-all package1 --collect-all package2 --collect-all package3 script.py

比如我们的脚本有import gradio,我们需要明确告诉pyinstaller需要用到的包,不然运行会提示缺少依赖。

When using Gradio with PyInstaller, especially with the --collect-all option, you often need to explicitly tell PyInstaller to include certain packages because Gradio relies on dynamic imports and may not be fully detected by PyInstaller's default analysis.

可以直接问人工智能需要哪些包,然后修改下执行的命令,如:what packages we need to collect with --collect-all option when using Gradio with PyInstaller?大模型会直接生成相应的指令:

pyinstaller your_gradio_app.py --onefile --collect-all gradio --collect-all gradio_client

2.

如果你的程序需要外部的data,而不是Python的Libraries,这时候也是需要手动把这些data添加进去:

If your program depends on access to certain data files, you can tell PyInstaller to include them in the bundle as well. In order to locate included files at run time, your program needs to be able to learn its path at run time in a way that works regardless of whether or not it is running from a bundle. This is covered under Run-time Information.

You can refer to the option--add-data SOURCE:DEST. The argument value should be in form of source:dest_dir, where source is the path to file (or directory) to be collected, dest_dir is the destination directory relative to the top-level application directory, and both paths are separated by a colon (:). 

如何准确知道需要哪些包?

需要创立一个虚拟环境,然后运行pip list查看看虚拟环境有安装了哪些Libraries

To check which Python libraries are installed in a virtual environment, you can use the following method inside the activated virtual environment

理论上不是所有的包都需要手动添加,因此只需要先打包,运行提醒缺少什么包的时候,再手动添加需要的packages。