Bootstrap

Python源文件(.py)及Python项目打包成可执行文件(.exe)的一些总结(主要针对一些坑)

最近我在将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 是打包成一个文件
-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 scriptscd 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所在目录下再运行就行了。

最后,希望你看完本文后有所帮助!

;