PyInstaller打包模型文件
最近需要将python项目打包成可执行文件,研究了下,记录下整个过程。项目是基于mxnet实现的一个物体检测器,需要打包成exe文件(windows)和linux的可执行文件,选择PyInstaller作为打包工具。主要有三个问题需要注意:
1.由于PyInstaller会将python环境中的所有安装包都打包进去,所以最好新建一个虚拟环境,只安装项目中需要的安装包
2. 模型和配置文件等静态资源,添加时注意其打包路径,以及代码运行时如何寻找这些静态文件
3. 项目中有多个py文件,主函数入口py文件,需要能找到这些文件
打包步骤整理如下:
1 环境安装
1.1 创建虚拟环境
采用virtualenv创建一个新的python虚拟环境,只安装脚本需要的模块,如下所示:
#windows系统 virtualenv --no-site-package --python="D:\Anaconda3\python.exe" package_test #在当前目录下,利用virtualenv创建一个空的python虚拟环境,名字为packgae_test cd package_test/Scripts #进入python虚拟环境目录 ./activate #激活python虚拟环境 pip install -i https://pypi.douban.com/simple/ opencv-python zmq mxnet-cu101 gluoncv Pyyaml #通过豆瓣镜像源,安装脚本需要用到的包opencv-python, zmq, mxnet-cu101, gluoncv,pyyaml #linux系统 virtualenv --no-site-package --python="D:\Anaconda3\python.exe" package_test #在当前目录下,利用virtualenv创建一个空的python虚拟环境,名字为packgae_test cd package_test/bin #进入python虚拟环境目录 source ./activate #激活python虚拟环境 pip install -i https://pypi.douban.com/simple/ opencv-python zmq mxnet-cu101mkl gluoncv Pyyaml #通过豆瓣镜像源,安装脚本需要用到的包opencv-python, zmq, mxnet-cu101mkl, gluoncv,pyyaml
1.2 安装PyInstaller
采用PyInstaller作为python打包工具,将python脚本打包成单独的exe文件。官方文档:https://pyinstaller.readthedocs.io/en/stable/
pip uninstall setuptools pip install setuptools==44.0.0 #安装PyInstaller之前需要卸载默认的最新版本的setuptools,安装44.0.0或者之前版本的setuptools pip install -i https://pypi.douban.com/simple/ PyInstaller ##通过豆瓣镜像源,安装 PyInstaller
1.3 Pyinstaller源码编译
当打包文件的大小超过2G时,pyinstaller打包会失败,需要修改Pyinstaller中的限制,修改后重新编译即可。
1. 从github下载源码(https://github.com/pyinstaller), 修改代码 2. 修改源码后重新编译: cd /bootloader python ./waf distclean all 3. 安装编译后的代码: cd .. python setup.py install
2. 代码整理
2.1 多个py文件的依赖关系
确定项目的入口py文件,需要对代码进行整理,确保pyinstaller能通过主文件找到导入的其他py文件。这里有两种方式:
A. 代码如果比较简单,可以直接将所有代码写入到入口py文件中,简单粗暴。
B. 代码文件比较复杂,需要在入口py文件中检查下相关导入的import语句(实验中发现通过将sys.path加入包路径的情况,打包后运行时会出现找不到模块的问题),如下面例子中,在main.py中导入detection文件夹下的detection.py文件:
#测试通过的导入方式 from .detection import detection #运行报错导入方式 import sys sys.path.append(sys.path[0]+"/detection") import detection
2.2 模型文件路径解析问题
PyInstaller可以将模型文件一起bundle到exe中,当exe在运行时,会生成一个临时文件夹,程序可通过sys._MEIPASS访问临时文件夹中的资源,我们打包进去的模型文件和配置文件也会解压到此处;而程序只会在执行路径下搜索模型文件,因此会找不到模型参数文件,所以需要在代码中将模型参数的路径转化为 “临时文件目录+打包路径” 格式,参见如下resource_path()函数。
def resource_path(relative_path): """ Get absolute path to resource, works for dev and for PyInstaller """ base_path = getattr(sys, '_MEIPASS', os.path.dirname(os.path.abspath(__file__))) return os.path.join(base_path, relative_path)
3. 脚本打包
在上面激活的python虚拟环境中,命令行执行下面打包命令
#windows示例 pyinstaller -F --add-data="D:\my_envs\package\Lib\site-packages\mxnet\*;./mxnet" --add-data="F:\python打包\package_test\param\detection-symbol.json;." --add-binary="F:\python打包\package_test\param\detection--0000.params;." --workpath=“F:\python打包\package_test\build” --distpath="F:\python打包\package_test\build\dist" “F:\python打包\package_test\build\main.py” 命令参数说明如下: -F 表示生成一个单独的exe --add-data="D:\my_envs\package\Lib\site-packages\mxnet\*;./mxnet" 添加虚拟环境中mxnet安装路径下的所有文件 (由于PyInstaller无法寻找到mxnet相关的dll文件,需要指明需要添加的文件) --add-data="F:\python打包\package_test\param\detection-symbol.json;." 添加模型结构文件 (;. 表示json文件添加到生成exe的同级目录) --add-binary="F:\python打包\package_test\param\detection--0000.params;." 添加模型参数文件 (;. 表示params文件添加到生成exe的同级目录) --workpath=“F:\python打包\package_test\build” 打包过程中产生的临时文件和日志文件存放目录 --distpath="F:\python打包\package_test\dist" 打包生成的exe文件目录 “F:\python打包\package_test\build\main.py” 为需要打包的入口py文件路径 #linux示例
linux的打包命令和windows类似,区别在于下面三个参数中符号区别(windows中;.表示同级目录, linux中:.表示同级目录)
命令参数说明如下: -F 表示生成一个单独的可执行文件 --add-data="/home/my_envs/package_test/lib/python3.7/site-packages/mxnet/*:./mxnet" 添加虚拟环境中mxnet安装路径下的所有文件 (由于PyInstaller无法寻找到mxnet相关的.so文件,需要指明需要添加的文件) --add-data="/home/param/detection-symbol.json:." 添加模型结构文件 (:. 表示json文件添加到生成可执行文件的同级目录) --add-binary="/home/param/detection-0000.params:." 添加模型参数文件 (:. 表示params文件添加到生成可执行文件的同级目录)
4. 运行exe文件
打包好的可执行文件在dist目录,第一次运行打包生成的exe文件时需要命令行执行,随后可以双击运行
参考文章:
https://www.cnblogs.com/ylsd80/p/10471936.html
https://blog.csdn.net/zlc0324/article/details/103697890
https://blog.csdn.net/m0_37477175/article/details/82146996