基于pyinstaller的算法代码单执行文件打包指南

832 阅读2分钟

环境:

  • 在一台可以正常运行算法的服务器上(否则在普通电脑(可能没有cuda或nvidia驱动等原因)打包的制品不可用
  • 运行一个algo的docker容器里并挂载算法代码(一定要采用python源代码,不能采用cython过的动态库)(参考命令:docker run -it --name one_file -v /home/imsight/one_file/ct_chest_lung_nodule/:/app registry.xxx.com/softwaredev… /bin/bash)

工具:

安装pyinstaller (pip install pyinstaller -i mirrors.aliyun.com/pypi/simple)

打包:

pyinstaller -F main.py(放射平台采用main.py作为启动文件)

pyinstaller打包时,有些特殊依赖文件不会放进来,可以额外声明加进去,例如:--add-binary '/usr/lib/x86_64-linux-gnu/libxcb.so.1:.'

如果运行时,出现缺失库的问题,根据经验,推荐的处理方式如下:

如果缺失的库定义在.py文件里,推荐采用hook的方式取代hiddenimports。

举例,运行时,缺失elasticapm库,会需要依次添加hidden library(每打包运行一次,才能发现缺失一个):

"elasticapm.transport", "elasticapm.transport.http", "elasticapm.processors", "elasticapm.instrumentation.packages", "elasticapm.instrumentation.packages.django"等等

非常浪费时间。

创建一个文件夹,举例叫hooks,里面放入hook-elasticapm.py,内容只有2句

from PyInstaller.utils.hooks import collect_submoduleshiddenimports = collect_submodules('elasticapm')

pyinstaller时,加入--additional-hooks-dir=./hooks 即可解决elasticapm系列的缺失库问题

在打包flask-limiter时,出现过如下错误:

pkg_resources.DistributionNotFound: The 'werkzeug' distribution was not found and is required by the application

hook里加入后面2句即可解决:

from PyInstaller.utils.hooks import collect_submoduleshiddenimports = collect_submodules('flask_limiter')# 新增这两句,解决pkg_resources.DistributionNotFound: The 'werkzeug' distribution was not found and is required by the applicationfrom PyInstaller.utils.hooks import copy_metadatadatas = copy_metadata('werkzeug')

注意:pip虽然安装的叫flask-limiter,但是import模块时是flask_limiter,因此,hook文件应该为hook-flask_limiter.py,文件里面也需要写为flask_limiter,否则是不成功的(多次测试验证)

如果库定义在cython生成的动态库里,应该采用--hidden-import

举例,模型的加密密码由于非常重要,不能明文出现在多人能访问的项目里。

一种做法是,一个只有极少数人能访问的仓库里实现这个模型的解密操作。

通过cython化后,输出二进制动态库,由项目的算法代码直接调用这个动态库。

由于pyinstaller无法直接搜索到这个cython化的文件里的import信息,因此,必须采用hidden-import的方式加入所使用的,例如Crypto.Cipher库。

这样pyinstaller打包时,才会加入Crypto.Cipher这个库。

制品:

默认在dist文件夹生成例如main(main.py去掉后缀)的可执行文件

测试:

一定要测试,如果打包缺失库,看不出明显的失败,必须要通过运行来测试

运行:

执行dist/main即可

注意:

目前,ubuntu18.04打包的执行文件,无法在ubuntu16.04上运行(因为18.04要求GLIBC的版本>=2.25)

因此,如果基于python3.6及以上的可执行文件,建议在ubuntu18.04打包并在ubuntu18.04的docker上运行。

以下是基于公版ubuntu:18.04镜像启动的命令:

docker run -it --rm --name sentinel_docker --privileged --device /dev/bus/usb:/dev/bus/usb -v /home/imsight/one_file/ct_chest_lung_nodule:/app -v /data:/data -p 6314:6314 ubuntu:18.04 bash -c "export LANG=C.UTF-8;cd /app;./dist/main"