最近的暑期课程需要实现一个人脸检测,并做成有图形用户界面的软件,和队友商量后,决定我将核心部件——人脸检测封装成一个命令行工具。于是乎,我就有了将PyTorch项目打包成可执行文件的应用需求,关于Python打包,常用的工具包有Pyinstaller和Nuitka。由于Nuitka给我感觉更佳,于是乎,这篇文章就探讨如何将比较大的PyTorch项目打包成可执行文件。
当然,pytorch本身提供了一套成熟的部署方案,但是最近没时间去学
具体安装过程可以看看这篇文章:Python打包exe的王炸-Nuitka 。
安装完后,打开命令行,输入:
$nuitka -h
如果可以跳出nuitka的相关参数信息,那就说明安装成功了。
前排提示,请确保你的numpy的版本为1.16.*
,否则,最终的软件会报错:
ImportError: numpy.core.multiarray failed to import
为了一些不必要的麻烦,你可以通过脚本将项目缩成一个文件,在确保这单个Python文件可以运行后,开始我们的打包过程,我的人脸检测文件名为F_Detection.py
。由于nuitka
的参数比较多,所以我打算通过Python脚本来运行nuitka
,我们在同目录下新建一个文件build.py
,内容如下:
import os
def __main(main : str):
parameters = [
'--mingw64', # 使用gcc编译器来编译得到的C和C++源文件
'--standalone', # 构建独立软件,也就是将于系统有关的运行库和Python运行时打包
'--show-progress', # 展示打包过程
'--show-memory', # 打印打包时的内存占用
'--nofollow-imports', # 不打包import语句导入的包(因为nuitka自动导入的库有问题,后面我们会手动导入,这样成功率更高)
'--plugin-enable=pylint-warnings',
'--output-dir=dist' # 存放构建结果的文件夹
]
param_str = " ".join(parameters)
command = "nuitka {} {}".format(param_str, main)
os.system(command)
__main("F_Detection.py")
10秒之内就能打包完成。打开存放构建结果的dist
文件夹,内容如下:
其中的F_Detection.dist
就是最终的结果,完成后面的操作后,F_Detection.dist
就是一个独立的软件包了。而F_Detection.build
中则存放了构建过程中python转成的C源文件,你可以删掉。下面我们通过trial and error的方法来补充软件包缺失的第三方库依赖。
我们在./dist/F_Detection.dist
下打开命令行,输入.\F_Detection
:
提示缺少pywin32_bootstrap
,打开我们的Python解释器的目录,也就是这个:
找到了吗?然后我们去找这个依赖,打开./Lib/site-packages
,你所有安装的第三方库的Python源码都在这个文件夹下,这也是我们在补充构建软件的第三方库是频繁光顾的地方,请记住它的位置。
然后找到./win32/lib/pywin32_bootstrap.py
,把它复制粘贴到F_Detection.dist
中。然后继续:
发现这次是torch缺了,那么我们就去site-packages
里把torch搬过来:
我们继续试图运行:
一样的,将你的版本为1.1.6.*
的numpy包从site-packages
拷贝到软件包中。继续:
原来是少了typing_extensions.py
,这是python3.7的新特性,我还是加一下吧,这个文件就在site-packages
中,拷贝之。继续尝试:
拷贝cv2,继续:
pytorch的模型文件没有加进来,拷贝一下model.pth
到软件包中,继续:
成功了,程序成功返回了bounding box。将F_Detection.dist
改个名字(如果你愿意),那么一个可以在Windows操作系统上分发的软件包就制作完成啦。
不要太相信Nuitka
的自动打包参数(PyQt5的还可以的),试了一些以后发现,最稳妥的打包方式就是用最基础的打包参数(记住一定要加入--nofollow-imports
参数)打包后,自己手动搬运第三方库以及第三方依赖(比如图片,模型文件,数据库文件)