前言:由于工作需求,需要使用Pyinstaller库将Python脚本打包成exe文件,特此花几天时间查找资料,进行实验。将过程做个梳理,记录下来,方便自己和他人日后查询。
目录
一、安装PyInstaller包二、打包深度学习模型(1) 生成spec文件(2) 修改spec文件(3) 运行spec文件进行打包三、常见问题分析四、结论一、安装PyInstaller包
由于需要在Anaconda的虚拟环境中进行打包,因此最好将PyInstaller包安装在虚拟环境中,先激活虚拟环境,再用以下命令进行安装。
pip install pyinstaller
二、打包深度学习模型
(1) 生成spec文件
本文是利用spec文件对整个项目进行的打包,直接输入命令进行打包也可以,但是一般只适合简单的脚本文件,像深度学习模型的工程文件一般比较复杂,文件之间的引用会比较多,因此更加适合使用spec文件进行打包。首先切换到工程所在的目录下,然后激活模型运行需要的环境,本文为
conda activate aideploy
注:如果没有激活模型运行需要的虚拟环境就进行打包,打包之后的exe运行会出现找不到相关库的报错。
然后执行以下命令生成spec文件
pyi-makespec -w xxx.py
(其中xxx.py文件为需要执行的主文件,深度学习模型中一般为推理文件,本文中为demo.py),如下图所示即为在同级目录下生成的spec文件。
(2) 修改spec文件
默认生成的spec文件如下所示,由于我打包的主文件是demo.py,因此生成的spec文件名称为demo.spec,文件和demo.py在同一个文件夹下,初始的内容如下所示。
# -*- mode: python ; coding: utf-8 -*-block_cipher = Nonea = Analysis(['demo.py'],pathex=[],binaries=[],datas=[],hiddenimports=[],hookspath=[],hooksconfig={},runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False,)pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)exe = EXE(pyz,a.scripts,[],exclude_binaries=True,name='demo',debug=False,bootloader_ignore_signals=False,strip=False,upx=True,console=True,disable_windowed_traceback=False,argv_emulation=False,target_arch=None,codesign_identity=None,entitlements_file=None,)coll = COLLECT(exe,a.binaries,a.zipfiles,a.datas,strip=False,upx=True,upx_exclude=[],name='demo',)
需要更改几个位置内容。
1、将打包文件引用到的文件夹其它文件的路径进行声明,如下图所示使用列表的形式给出。
a = Analysis(['demo.py',"E:\\深度学习部署相关\\DSFD-VGG16-EfficientNet-master\\data\\config.py","E:\\深度学习部署相关\\DSFD-VGG16-EfficientNet-master\\models\\factory.py","E:\\深度学习部署相关\\DSFD-VGG16-EfficientNet-master\\utils\\augmentations.py","E:\\深度学习部署相关\\DSFD-VGG16-EfficientNet-master\\models\\DSFD_efficient_b0.py","E:\\深度学习部署相关\\DSFD-VGG16-EfficientNet-master\\models\\DSFD_efficient_b1.py","E:\\深度学习部署相关\\DSFD-VGG16-EfficientNet-master\\models\\DSFD_resnet.py","E:\\深度学习部署相关\\DSFD-VGG16-EfficientNet-master\\models\\DSFD_vgg.py",],pathex=["E:\深度学习部署相关\DSFD-VGG16-EfficientNet-master"],binaries=[("E:\深度学习部署相关\DSFD_Demo\weights\dsfd_face.pth", "weights")],datas=[],hiddenimports=[],hookspath=[],hooksconfig={},runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False,)
2、其中pathex给出需要打包的模型文件夹路径。
3、data列表以元组的形式给出需要拷贝的其它非py文件(包括但不限于模型文件或测试图片),其中元组的形式为(“需要拷贝的数据绝对路径”, “拷贝到打包文件夹下的文件夹名称”)。具体如上图所示本文使用的demo.py需要从同级文件夹下的weights\dsfd_face.pth加载模型文件,因此我们打包之后会在打包文件夹下生成weights文件夹以及在其中拷贝过来的dsfd_face.pth模型文件,这样exe文件就可以直接调用模型文件,不用更改路径了。
4、关于hiddenimports以及excludes两个列表的修改,本人在打包过程中并未对其进行额外的修改。但是有些教程反应如果打包提示找不到相对应的包,可能需要添加相应字段。
(3) 运行spec文件进行打包
修改spec文件后直接如下调用如下命令进行打包,需要注意此时必须在激活模型运行所需虚拟环境的前提下进行打包,否者会出现找不到引用第三方库的报错。
pyinstaller -D demo.spec
但是上述命令有人反应会运行不成功,可以使用如下命令尝试。
pyinstaller demo.spec
打包成功将会在模型工程文件夹下新生成两个如图所示文件夹,build以及dist,我们所需的打包文件就下dist文件夹下。
三、常见问题分析
1、需要将深度学习代码运行环境激活,再进行模型打包,不然将导致找不到对应的包,或者相关依赖文件找不到。
2、直接运行exe文件时如果运行不成功可能会出现闪退的问题,无法看到报错信息进行Debug,我们可以使用命令行运行exe文件,这样就可以看到输出信息,从而可以方便进行改错。
3、关于模型文件中引入的第三方库(比如torch、os、numpy)等库的打包,本人在实验中并不需要进行额外的声明,只要在激活虚拟环境的前提下进行打包,PyInstaller会自动将需要的第三方库打包到dist文件夹下。
四、结论
我们在打包模型的时候是单个文件打包还是文件夹打包?
用pyinstaller打包pytorch的感觉就是大,已经尽力用from import代替import之类的方式减少了导入的库内容,但还是打包出了一个巨大无比的应用程序。我的打模型打包为文件夹需要4.3G,而打包为单个exe文件则是需要1.5G,这样看好像是打包为exe文件更好,结构既简单占用空间又小,但是怎么会有这么十全十美的事呢?
首先是启动速度,打包为文件夹的情况下,启动基本是秒启动,但是打包为一整个exe文件,启动就需要将近30s才能print出第一行提示语句……
其次,打包为整个exe文件之后,它每次运行都会把相当于整个文件夹的内容释放到一个c盘的临时文件夹中,而且它不会马上删除!试运行了几次之后,你的C盘就会爆炸,而打包为文件夹,每次运行就只会再打包的文件夹下运行。
经过几天的研究本人发现使用PyInstaller打包模型文件只是可以方便不会使用Python脚本的研究人员使用,并不适用于工作中实际任务的深度学习模型部署(无论是速度还是占用空间,都不满足要求)。
本文已尽量把具体过程记录详细,但可能各位读者参考教程还是会遇到各种各样的问题,欢迎大家留言讨论。