python--pipenv环境下使用pyinstaller打包py脚本遇到的坑

因工作需要,要将python脚本打包成可执行的exe文件,网上大多数都是用pyinstaller,遂本文也使用了pyinstaller进行打包。在安装完以及打包完之后发现,exe文件大小有290M!几个脚本文件加起来的大小也不过几十KB,这么大的打包文件也太夸张了。于是搜索了一下如何减小打包文件的大小,看到网上很多都是说因为使用anaconda安装了python,而anaconda会安装很多库文件,因此在打包过程中会将很多不需要用到的库文件也打包进去。给出的解决办法有两种,一种是将anaconda卸载,在官网下载纯python安装,需要的库再去安装;第二种方法是开辟一个虚拟环境,在虚拟环境下安装需要的依赖包。
第一种办法太过繁琐,而且安装了一些依赖包以后,下一次打包需要的又不一样,难道又要卸载重装?遂采用了第二种方式,构建虚拟环境。网上推荐的是采用pipenv搭建虚拟环境,本文也就采用了该方法。
方法可参考:
知乎回答
pipenv解决pyinstaller打包过大问题
pipenv搭建虚拟环境
pipenv管理项目

按照上面的链接搭建好环境,并打包好你的python脚本文件,结果显示打包成功。

No module named ‘win32com’

别急,打包显示成功不一定就表示打包就没有问题。首先看下打包过程中终端上面显示的提示信息中是否有报错,笔者就发现下面的报错信息:
python--pipenv环境下使用pyinstaller打包py脚本遇到的坑_第1张图片
提示报错信息是缺少名为’win32com’的模块,网上只找到一个比较接近的答案 解决python提示No module named ‘win32com’ 大致应该是缺少了pywin32扩展包。
先在虚拟环境中用 pipenv graph查看已经安装的依赖包,发现确实没有pywin32扩展包。
执行以下命令安装:

pipenv install pywin32

安装完成以后用pipenv graph查看,可以看到已经安装好的pywin32依赖包。
python--pipenv环境下使用pyinstaller打包py脚本遇到的坑_第2张图片
安装好该依赖包以后,pyinstaller打包过程中便没有再出现该报错信息。

No module named ‘distutils’

至此,打包过程应该是没有问题,下面就是测试打包的exe文件是否可以正常执行。需要注意的是如果代码中没有图形用户界面,最好是在命令行窗口(如果python脚本中有shell命令,则必须在Linux终端窗口,或者可执行shell命令的窗口,如git bash)中执行exe文件,因为exe执行过程中生成的命令行窗口会闪一下就消失了,无法看到执行的结果信息,是否报错也无从得知。而在命令行窗口执行可以看到结果信息。
好了,开始执行exe文件。并没有想象中那么顺利,显示的报错信息:ModuleNotFoundError: No module named ‘distutils’
python--pipenv环境下使用pyinstaller打包py脚本遇到的坑_第3张图片
这个报错信息在网上搜到的有两种解决办法,一种是用 sudo apt-get 命令安装 python3-distutils 依赖包,该方法并不能在pipenv虚拟环境中执行,提示没有该命令,而采用pip installl或者pipenv install也不能安装该依赖包;另一种方法是将虚拟环境版本降级,但是貌似用的是virtualenv,并不是本文用的pipenv。因此只能再另寻他法了。
幸运的是,在浏览了大量网页之后,在一个github中找到了解决办法:distutils not included with latest virtualenv (16.4.0) #4064
python--pipenv环境下使用pyinstaller打包py脚本遇到的坑_第4张图片
按照该网页中的说法,打包过程的提示信息为:

2556 INFO: distutils: retargeting to non-venv dir 'd:\\anaconda\\Lib\\distutils\\__init__.py'

这个表明 “distutils modules are not included into the final executable binary.” 也就是说distutils 模块不在最终的打包文件中。
解决的方法是将上面图片中热心网友发的那段代码放到打包生成的一个后缀为spec的文件的开头。保存之后在命令行使用如下命令重新打包(请勿使用pyinstaller -F file.py,这样会覆盖之前的文件,spec中添加的代码也会被覆盖):

pyinstaller file.spec

重新打包之后在提示信息中发现,之前的distutils提示变成了:

2556 INFO: distutils: retargeting to non-venv dir 'd:\\anaconda\\Lib\\distutils'

而打包的exe文件也可以正确运行了,太不容易了…
不过,打包之后的文件大小好像减小的不是很多,变成了219M,虽然减小了,但还不够。按照网上的说法,是因为python脚本中使用了pandas或者numpy库,这两个库打包之后会加进去很多依赖库,因此打包文件会很大。
于是笔者将脚本中用到pandas库的地方用别的方式替换掉,最后重新打包,文件只有6.16M了!
pandas读取csv文件替换方法

其他可能会出现的问题

打包过程很有可能会碰到:
pyinstaller creating EXE RuntimeError: maximum recursion depth exceeded while calling a Python object
pyinstaller打包报错: RecursionError: maximum recursion depth exceeded
笔者在非虚拟环境下运行的时候有遇到这个问题,解决办法就是在生成的spec文件开头加如下代码:

import sys
sys.setrecursionlimit(5000)

但是在虚拟环境下打包没有碰到这个问题,先备注一下。
在打包引入pandas库的python脚本时有碰到:numpy: No module named ‘numpy.random.common’ 解决的方法是在python脚本引入pandas前加如下代码:

import numpy.random.common
import numpy.random.bounded_integers
import numpy.random.entropy

你可能感兴趣的:(python,工具使用问题,报错信息处理)