????????前言:随着深度学习算法的流行,在传统工业软件计算领域,传统算法逐渐被深度学习算法给代替,但由于基于python的深度学习算法十分依赖python环境以及例如Pytorch、Scikit-learning、Keras等机器学习库,将深度学习算法运用集成到实际生产中去时,需要随身带着这一大坨库(通常用Anaconda管理)和python解释器,很不方便,因此Pyinstaller是个很实用的工具,能将其打包为独立的可执行程序。
????????PyInstaller的历史最早可以追溯到2008年,Hartmut Goebel开发并发布了第一个版本。随着时间的不断发展,Pyinstaller已成为应用最为广泛的python打包工具。其基本原理为(参考https://blog.csdn.net/Dontla/article/details/131474870):
? ? ? ? 安装Pyinstaller有多种方法:
pip install pyinstaller
? ? ? ? 打包单独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 #用于指定加密算法,如果不需要加密可以设置为None
SETUP_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,或者是与目标运行系统不兼容