前言:随着深度学习算法的流行,在传统工业软件计算领域,传统算法逐渐被深度学习算法给代替,但由于基于python的深度学习算法十分依赖python环境以及例如Pytorch、Scikit-learning、Keras等机器学习库,将深度学习算法运用集成到实际生产中去时,需要随身带着这一大坨库(通常用Anaconda管理)和python解释器,很不方便,因此Pyinstaller是个很实用的工具,能将其打包为独立的可执行程序。
一、Pyinstaller简介
PyInstaller的历史最早可以追溯到2008年,Hartmut Goebel开发并发布了第一个版本。随着时间的不断发展,Pyinstaller已成为应用最为广泛的python打包工具。其基本原理为(参考https://blog.csdn.net/Dontla/article/details/131474870):
- 分析脚本:PyInstaller会分析Python脚本,识别出脚本中所引用的库和资源文件。
- 创建打包规范:根据分析结果,PyInstaller会生成一个打包规范文件,即xxx.spec文件,其中包含了脚本的依赖关系、资源文件等信息。
- 打包依赖库:PyInstaller会将脚本所依赖的库文件进行打包,这些库文件会被嵌入到可执行文件中。
- 生成可执行文件:根据打包规范和打包的依赖库,PyInstaller会生成一个独立的可执行文件,该文件包含了Python解释器、脚本代码和依赖的库文件。
- 运行可执行文件:生成的可执行文件可以在其他机器上直接运行,无需安装Python解释器和相关库。
安装Pyinstaller有多种方法:
pip install pyinstaller
二、单独的py文件
打包单独py文件,使用以下命令即可:
pyinstaller your_script.py
PyInstaller提供了一些自定义打包选项,可以通过执行pyinstaller --help命令查看,常用的包括以下选项:
可选参数:-h, --help 显示帮助信息并退出-v, --version 显示程序版本信息并退出。--distpath DIR 指定打包应用的目录(默认为./dist)--workpath WORKPATH 指定所有临时工作文件(.log, .pyz等)的目录(默认为./build)-y, --noconfirm 替换输出目录(默认为SPECPATH/dist/SPECNAME)而不需要确认--upx-dir UPX_DIR UPX工具的路径(默认为搜索执行路径)-a, --ascii 不包含Unicode编码支持(默认情况下如果可用则包含)--clean 在构建之前清理PyInstaller缓存和临时文件。--log-level LEVEL 构建时控制台消息的详细程度。LEVEL可以是TRACE、DEBUG、INFO、WARN、DEPRECATION、ERROR、FATAL之一(默认为INFO)。也可以通过PYI_LOG_LEVEL环境变量进行设置。生成内容:-D, --onedir 创建一个包含可执行文件的单文件夹捆绑包(默认)-F, --onefile 创建一个单文件捆绑的可执行文件。--specpath DIR 存储生成的.spec文件的文件夹(默认为当前目录)-n NAME, --name NAME 分配给捆绑应用和.spec文件的名称(默认为第一个脚本的基本名称)捆绑什么,搜索什么:--add-data <SRC;DEST or SRC:DEST>添加到可执行文件的附加非二进制文件或文件夹。路径分隔符是平台特定的,使用``os.pathsep``(在Windows上为``;``,在大多数Unix系统上为``:``)。此选项可以多次使用。--add-binary <SRC;DEST or SRC:DEST>添加到可执行文件的附加二进制文件。有关详细信息,请参见``--add-data``选项。此选项可以多次使用。-p DIR, --paths DIR 搜索导入的路径(类似于使用PYTHONPATH)。可以使用多个路径,用``':'``分隔,或多次使用此选项。相当于在.spec文件中提供``pathex``参数。--hidden-import MODULENAME, --hiddenimport MODULENAME指定在脚本代码中不可见的导入模块。此选项可以多次使用。--collect-submodules MODULENAME收集指定包或模块的所有子模块。此选项可以多次使用。--collect-data MODULENAME, --collect-datas MODULENAME收集指定包或模块的所有数据文件。此选项可以多次使用。--collect-binaries MODULENAME收集指定包或模块的所有二进制文件。此选项可以多次使用。--collect-all MODULENAME收集指定包或模块的所有子模块、数据文件和二进制文件。此选项可以多次使用。--copy-metadata PACKAGENAME复制指定包的元数据。此选项可以多次使用。--recursive-copy-metadata PACKAGENAME复制指定包及其所有依赖项的元数据。此选项可以多次使用。--additional-hooks-dir HOOKSPATH指定额外的钩子路径。此选项可以多次使用。--runtime-hook RUNTIME_HOOKS指定自定义运行时钩子文件的路径。运行时钩子是与可执行文件捆绑在一起的代码,在任何其他代码或模块之前执行,用于设置运行时环境的特殊功能。此选项可以多次使用。--exclude-module EXCLUDES忽略的可选模块或包(Python名称,而不是路径名称)。此选项可以多次使用。--splash IMAGE_FILE (实验性功能) 向应用程序添加一个带有图像IMAGE_FILE的启动画面。启动画面可以在解压过程中显示进度更新。如何生成:-d {all,imports,bootloader,noarchive}, --debug {all,imports,bootloader,noarchive}提供用于调试冻结应用程序的帮助。此参数可以多次提供以选择以下选项之一。- all: 以下所有选项。- imports: 指定-v选项给底层Python解释器,导致它在每次初始化模块时打印一条消息,显示加载模块的位置(文件名或内置模块)。参见https://docs.python.org/3/using/cmdline.html#id4。- bootloader: 告诉引导加载程序在初始化和启动捆绑应用程序时发出进度消息。用于诊断缺少导入的问题。- noarchive: 将所有冻结的Python源文件存储为结果可执行文件内的存档,而不是文件存储在结果输出目录中。--python-option PYTHON_OPTION指定要在运行时传递给Python解释器的命令行选项。目前支持"v"(等效于"--debug imports")、"u"和"W<warning control>"。-s, --strip 对可执行文件和共享库应用符号表剥离(不推荐在Windows上使用)--noupx 即使可用,也不使用UPX(在Windows和*nix之间的工作方式不同)--upx-exclude FILE 使用upx时防止对二进制文件进行压缩。如果upx在压缩过程中破坏某些二进制文件,通常会使用此选项。FILE是二进制文件的文件名,不包含路径。此选项可以多次使用。
原文链接:https://blog.csdn.net/Dontla/article/details/131474870
生成的各个目录和文件的作用如下:
build/
:该目录是pyinstaller生成的临时目录,用于存放编译过程中生成的中间文件和临时文件。dist/
:该目录是pyinstaller生成的最终目录,用于存放编译后生成的可执行文件或打包后的应用程序。-
XXX.spec
:pyinstaller的配置文件,用于指定编译的参数和选项,如果在目标系统中需要重新编译应用程序,可以将该文件一同拷贝过去。
在实际运行可执行程序时,经常会出现找不到XXX的报错,由于pyinstaller没有自动识别到隐藏模块,解决方法一般是在打包过程中用--hidden-import jtop
参数来显示地导入该模块
三、打包多文件项目
当对包含多个文件夹的项目进行打包时,需要生成配置文件XXX.spec,并自定义各个配置项,以当前这个测试项目为例,Data目录下为自定义的csv文件,mnist_data下为下载的公开数据集,DNN下为模型定义py,main.py为主程序入口。
执行命令生成xx.spec文件:
pyi-makespec -F main.py
如下所示,可以看到spec文件本身是一个python文件:
# -*- mode: python ; coding: utf-8 -*-block_cipher = None #用于指定加密算法,如果不需要加密可以设置为NoneSETUP_DIR ='C:\\wjy\\Python_project\\deepLearning\\'#分析器,用于指定需要编译的Python脚本文件、路径、二进制文件、数据文件
a = Analysis(['main.py',SETUP_DIR + 'DNN\\DNN.py'],#需要编译的Python脚本文件列表(可以是相对路径)pathex=[], #额外的模块搜索路径,指定pinstaller无法自动检测到的模块binaries=[], #需要包含的二进制文件,包含了动态链接库或共享对象文件,在运行之后会自动更新datas=[("Data","Data"),("mnist_data","mnist_data")], #需要包含的数据文件,每个元素都是一个元组(文件的源路径,在打包文件中的路径)hiddenimports=[], #需要导入的隐藏模块,pyinstaller无法自动检测到的模块hookspath=[], #自定义的查找pyinstaller钩子的路径hooksconfig={}, #自定义的钩子配置,是一个字典runtime_hooks=[], #运行时钩子,本质是一个python脚本,在脚本运行前运行用于准备环境excludes=[], #需要排除的模块win_no_prefer_redirects=False, #在Windows上禁用优先重定向win_private_assemblies=False, #在Windows上使用私有程序集cipher=block_cipher, #加密算法noarchive=False, #是否生成归档文件
)#生成的Python字节码文件,在运行时会被解压缩到临时目录中,然后被加载和执行
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) #纯净的Python字节码文件,压缩的数据,加密算法#生成的可执行文件
exe = EXE(pyz, #Python字节码文件,包含了所有纯python模块a.scripts, #附加的脚本文件a.binaries, #附加的二进制文件a.zipfiles, #附加的压缩文件a.datas, #附加的数据文件[], #所有需要打包到exe文件内的二进制文件name='main', #生成的可执行文件的名称debug=False, #打包过程是否打印调试信息bootloader_ignore_signals=False,strip=False, #是否移除所有的符号信息,使打包出的exe文件更小upx=True, #是否使用UPX压缩exe文件upx_exclude=[], #需要排除的UPX压缩文件runtime_tmpdir=None,console=True, #是否为控制台应用程序,true则在控制台窗口运行,否则作为后台进程运行disable_windowed_traceback=False, #是否禁用窗口化的回溯argv_emulation=False, #是否启用命令行参数模拟target_arch=None, #目标系统的架构,确保打包的应用程序在目标系统上能够正常运行codesign_identity=None, #代码签名标识entitlements_file=None, #授权文件
)
其中datas=[("Data","Data")]意思是将main.py当前目录下的Data目录(及其目录中的文件)加入目标exe中,在运行时放在临时文件的根目录下,名称为Data。
然后使用pyinstaller命令即可根据配置文件生成可执行程序:
pyinstaller XXX.spec
四、常见问题
1、打包输出后的exe文件执行时,报错“找不到xxx 文件”
一般两种解决方案,在spec文件中的" hiddenimports=[]"添加漏掉的包;如果该方法不起效,则直接把对应的文件复制到dist目录下即可,例如在该实例中,运行时报错“找不到pytorch_lightning/ version.info”,则直接在anaconda环境中将该文件复制过去即可。
2、exe运行时函数或python语句报错
一般是python包版本错误例如cpu环境中安装cuda版本的Pytorch,或者是与目标运行系统不兼容