最近我在将Python源文件打包成可执行文件时遇到了一些坑,主要是将一个连接mysql数据库以及可视化分析的项目打包。这里记录下来,顺带一些坑总结分享给大家。
本文主要分为两大模块:
一、在Python或Anaconda环境下进行打包(可执行文件较大)。
二、在Python虚拟环境下打包(可执行文件较小)。
一、 在Python或Anaconda环境下进行打包
前期准备:Anaconda或Python的相关环境。我这里用的是Anaconda(Anaconda牛逼!)。下面开始:
首先,下载pyinstaller。pyinstaller 这个包就是用来将Python源文件打包的。
打开anaconda的控制台,用pip或者conda都行。
pip install pyinstaller
安装成功之后,为了方便,将你想要打包的.py文件放到一个文件下,为了展示方便,我这里的.py文件(hello.py)就只是输出“hello”。我这里放到D盘的test目录下,然后进入这个目录文件,执行
pyinstaller -F hello.py
-F 这里是打包成一个文件。
成功之后,我们可以看到在test文件目录下多了一些文件,这里我们需要的.exe文件就在dist这个文件目录下。
在 anaconda控制台进入dist目录执行下,
这里说明我们已经成功了。
下面我打包一个查询本地mysql数据库信息的.py文件(我后面作对比会贴出来),说一下一些坑。
首先,就是缺少相应模块的问题
如果在打包过程中遇到了提示如缺少XXX module,
如这里,缺少pymysql这个包。
那你就下载相应的包进去,
pip install xxx (xxx为相应的包名)
下载包成功之后,需要删除你之前生成的__pycache__,build,dist,.spec这些文件,就是只剩下一个.py文件再运行 pyinstaller -F xxx.py
来打包。
再说一些具体的,如:
UnicodeDecodeError: ‘utf-8’ codec can’t decode byte 0xce in position
需要先运行 chcp 65001
再运行 pyinstaller -F xxx.py
来打包。
然后就是这个坑: Cannot find existing PyQt5 plugin directories
这里可以参考这个博客 https://blog.csdn.net/m0_37534550/article/details/86481785。
最后,我以我写的这个查询数据库的.py文件为例子,代码如下:
import pymysql as p
import pandas as pd
conn=p.connect(host='127.0.0.1',user='root',passwd='root',db='test')
def read_from_db(table_name):
sql = "select * from " + table_name
df = pd.read_sql(sql,conn)
return df
data=read_from_db('try')
print(len(data))
如果你要用的话,记得事先配置好mysql数据库中相应的表。
打包过程和上面一样,不再说明了。
可以看到我这里就引入了两个包,pymysql和pandas ,且代码量也很少,但是看看生成的.exe文件(打包过程和上面一样)
279M!!!
279M!!!
279M!!!
这样不仅你生成这个.exe的过程比较慢,执行起来也很慢,更别说它占这么大的空间了。
原因:我查了下,这个打包应该是打包了Python的解释器,以及比如我这里用的Anaconda里内置的很多库,打包的时候打包了很多不必要的模块进去,因此造成了可执行的文件很大。
解决方法:用Python虚拟环境来打包。
因此下面讲在python虚拟环境下打包。
二、在Python虚拟环境下打包
首先是下载virtualenv这个包。这里又由一个大坑,容我慢慢道来。
你需要下载16.1的virtualenv版本,否则你可能在打包时会出现这个错误:
ModuleNotFoundError: No module named 'distutils’
并且你在虚拟环境里面也下载不了这个distutils包(很难受),哎这也是折磨了我半个小时的坑。
因此首先是下载virtualenv 16.1的版本,打开cmd(你需要有python环境),安装这个版本
pip install virtualenv==16.1
这里,如果你之前安装了virtualenv的其他高版本,并且建了虚拟环境的,可以通过
virtualenv --version
来查看自己的版本。如果不是16.1版本,先卸载
pip uninstall virtualenv
卸载完了,再重新安装
pip install virtualenv==16.1
并且需要重新在一个文件内新建一个虚拟环境。
总而言之,确保自己安装的virtualenv是16.1的版本。
安装成功后,我们继续,我们需要在某个盘下新建一个文件,并在这个文件下建立一个虚拟环境。如我这里在D盘新建一个env文件,
cmd下进入这个env文件,
我们在env里面新建一个名为test的虚拟环境,
virtualenv test
这里我们就建立了一个名为test的python虚拟环境,可以从图中看到是以D盘的python作为解释器。
打开env文件,可以看到多了个test文件,且test里面也多了如Scripts文件等。
接下来我们进入虚拟环境,进入test的Scripts目录下,
activate
这里cd scripts
和 cd Scripts
一样,文件目录不分大小写。
可以看到控制台的最左边出现<test>
,说明此时你就在这个名为test的Python虚拟环境下了。顺带说下,需要退出这个虚拟环境,也同样是在scripts下,执行
deactivate
进入虚拟环境,首先确认下自己的virtualenv版本,
16.1.0,没问题。
然后就是下载pyinstaller,方式和之前一样,
pip install pyinstaller
以上是下载成功截图。
这里必须在虚拟环境内重修下载pyinstaller,否则的话,你在虚拟环境里虽然可以用pyinstaller,但默认是你之前Python或Anaconda中的pyinstaller。
下载完成后,我还是以我之前的那个查询数据库的.py文件为例子,相应代码可以参考上面。可以知道,我导入了这两个包,
import pymysql as p
import pandas as pd
*我先不在虚拟环境内下载这些包,看看会出现什么,以及该怎么做。
*
好的,我们开始用pyinstaller来打包,过程和第一个模块讲的差不多。也是将需要打包的.py文件放到这个虚拟环境下,如我这里在test目录下新建了一个try文件,try文件里面有这个t.py文件
接下来cmd进入try里面打包,
这里打包成.exe虽然成功了,但不一定满足了我们的需求(因为我并没有在虚拟环境下载相应的包),我们进入dist,执行这个t.exe,看看结果
可以看到,这里明显缺少了pymysql这个包,那就应该去下载这个包,另外我这里应该还需要下pandas这个包,我这里也一并下载了,
ok,我导入的包都下载完了,删除try中的其他文件(删除时cmd需要退出到try目录),只剩t.py之后再重新打包一次,
ok,t.exe成功生成了。进入看看能不能运行,
可以看到,这里成功读取了test数据库里面的try表的有2895行。
那么我们看看,这个t.exe文件有多大呢?
25.7M !!!
25.7M !!!
25.7M !!!
这不到之前在Anaconda环境下生成的大小的1/10,同一个文件,因为过多的包导致大小完全不同。
以上在虚拟环境下就解决了生成的.exe文件过大的问题,在这里分享给大家。
另外还需要说一些(也很重要):
1、一般在虚拟环境里面缺少的包都是你的.py里面的导入的包,如果提示缺少相应的包就下载相应的包后,记得删除多余文件,再重新打包。
2、如果要打包多个.py,即一个项目,这里如果用pyinstaller 的话,可以这样
pyinstaller -F a.py b.py c.py d.py ......
其中a,b,c,d为相应文件名,他们之前用空格隔开。
3、这个生成的.exe是可以在不同的电脑上直接运行的(windows),但是比如我这个需要相应的数据库,你需要事前配置好数据库就行。或者是需要某些文件才能运行的项目,只需要将相应的文件放到.exe所在目录下再运行就行了。
最后,希望你看完本文后有所帮助!