后面代码的环境是在Windows子系统下的Ubuntu 20.04下进行的。vscode可以通过,配置WSL来进入环境(如下图)。
最近有一个需求是要把一个系统部署到某公司服务器上去。要部署的两台服务器分别是Centos、Ubuntu的,里面就是有一些模型使用python写的嘛。模型的调用是通过java的后端项目触发的,这个模型的python环境不好搞,所以要打包成liunx下的可执行文件。本来想着用wine
直接也可以触发exe的但是实际上发现还是挺麻烦的,不是很适配总是出现…not found。
我拿到的模型,用的tensorflow
的版本是1点几的是比较老的。先来看一下大致用到的哪些包和对应的版本,(注意其中的numpy的版本也不能太高)
为了适应这个tensorflow
的版本,需要的python版本不能大于3.8,我自己测试的话3.8的是不行的,3.7和3.6是ok的。然后这个需要对应的pyinstaller
的版本是3.4的,版本不对应也会出错。
安装步骤直接参照这篇 https://blog.csdn.net/zckui/article/details/89821101
步骤还是挺详细的,不过坑也在其中。(这里要注意的是,里面说的创建软连接的时候不要直接修改liunx自带的最好自己创建一个)
关键在那篇博客中的第五步
这里只指定了python编译安装的路径,没有指定别的。本以为是没是的,然后每次执行pyisntaller ...
打包的时候到下图所示时
的时候就报错
报错的意思差不多是说,自己下的python没有直接跟系统上自带的一些os链接在一起(跟自带的这些so文件版本不匹配)。
这个时候可以依次参考下面两篇博客:
博客1
这篇的话是针对我们编译时指定的参数的,跟前面的报错信息提示一样,博客中加的参数如下图
个人建议是
./configure --prefix= $pythonDownloadLocation --enable-shared --enable-ssl ## 记得要一次性输完,刚开始以为这个直接改里面配置信息的,分#两次输入就不能解决问题
然后再make && make install
跨过一号坑后,我们可以成功打包的流程:
Building EXE from EXE-00.toc completed successfully.
看到这个是非常激动的,但是当执行的时候又出了点问题。
astor 报错
错误信息
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/_MEIu22u7n/astor/VERSION'
看了网上别人的一些解决方案和分析。这个其实是astor
包里面的问题。
可以按照我下图的标注解决
新增的这个
__version__
等于多少应该问题不大,保险的话,可以在修改前通过pip list
看看这个astor
是什么版本的。
编辑之后保存修改,并且重新执行pyisntaller的打包命令。
tensorflow 包中报错
然后出现了tensorflow
包里面的报错:
tensorflow.python.framework.errors_impl.NotFoundError: /tmp/_MEIOH1ebc/tensorflow/contrib/bigtable/python/ops/_bigtable.so: cannot open shared object file: No such file or directory
这个其实是,跟前面报错的原因是类似的。应该是包里面引用某个文件的时候用错了路径,pyinstaller在打包的时候会有一个虚拟路径,一般有/tmp ....
里面的东西找不到的都是这个问题。然后可以跟着下面这篇文章解决这个问题 文章。
主要参考的回答:
翻译一下文章中的解决方案,一是要找到所有类似的.so
文件,可以通过以下代码进行查看:
import os
tsLocation = "/usr/local/python3.7/lib/python3.7/site-packages/tensorflow"
tensorflow_binaries = []
for dir_name, sub_dir_list, fileList in os.walk(tsLocation):
for file in fileList:
if file.endswith(".so"):
full_file = dir_name + '/' + file
print(full_file)
tensorflow_binaries.append((full_file, '.'))
print(*tensorflow_binaries)
输出大致如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MScUFoN0-1666597606845)(https://raw.githubusercontent.com/yuyuyu258963/pic-go-picStore/main/image-20221024152038101.png)]
可以把这些文件路径添加到对应的.spec
文件中
添加路径的注意和技巧:
- 注意添加的格式
("$path", ".")
- 注意前面的
/usr/local/python3.7
这段路径要换成自己python所在的路径- 技巧 可以同vscode上快捷编辑的方式,把前面代码中的输出复制进去然后按住鼠标滚动轮子,选中多行同时进行编辑。
下面我们去修改 tensorflow
包中导入这些文件的代码
根据上图的标注,然后修改保存。
然后执行pyinstaller ××××.spec
去打包文件。
到这里这个问题应该就解决了,
继续尝试运行打包后的可执行文件,结果出现了:
ModuleNotFoundError: No module named 'sklearn.utils._typedefs'
这个与前面的错误原因不太一样,下面给出一种简单的解决方法。在.spec
文件中的hiddenimports
中添加缺少的module.
添加后直接执行pyinstaller ./×××.spec
重新执行打包。
这次的报错就比较迷惑:
struct.error: 'I' format requires 0 <= number <= 4294967295
乍一看这个应该是什么越界了,然后就开始找解决方案。
然后就找到对这个问题分析的社区,https://github.com/pyinstaller/pyinstaller/issues/3939
意思是说,自己打包成的exe大小超过限制。在那上面我没有找到对应的解决方案,不过我猜测这个大小限制是对应打包成的exe(可执行文件)的大小限制。于是我尝试减少打包成的可执行文件的体积,终于找到了问题。pyinstaller
打包的时候可以指定以下几个常用命令:
因为之前我习惯使用pyinstaller -F -c ×××.py
这个命令去打包,刚刚好paddleocr
依赖的其它包有很多导致体积过大。
于是我使用打包命令pyinstaller -D -c ×××.py
,终于显示打包成功。包是打包成功了,但是使用的时候还有很多缺少模块的报错,比如下图
这个时候我们需要做的是从对应的路径里面包这个pywt拷贝到dist里面与可执行文件的同级目录中。注意:注意修改拷贝过去的文件的使用权限
。
之前就打包过多次python,除了系统缺少dll文件外的大部分报错都在这次任务中碰到了。现在想来想学学虚拟环境技术还是很必要的,后面还得学一下docker这样在后面部署的过程中也不必大费周折了。