part17:Python打包和发布(zipapp,PyInstaller)
知识点:
- 发布 Python 程序
- 使用 zipapp 生成可执行的 Python 档案包
- 使用 zipapp 创建独立应用
- 安装 PyInstaller 模块
- 使用 PyInstaller 生成 EXE 程序
经过一系列的开发、调试后得到的 Python 程序,接下来就是将这个程序发布出来。
两个常用的发布工具:zipapp 和 PyInstaller。
zipapp 模块生成可执行的 Python 档案包,该档案包包含目录下所有的 Python 程序。如果使用 pip 工具先将 Python 程序所依赖的模块下载到目录下,那么就可以生成可独立远行的 Python 程序,只要目示机器上安装有 Python 解释器环境即可。
PyInstaller 工具更强大,可以直接将 Python 程序编译成 Windows、Mac OS X 平台上的可执行程序,而无须这些机器上安装 Python 环境。
一、使用 zipapp 模块
zipapp 模块可以将一个 Python 模块(可能包含很多个源程序)打包生成一个 Python 应用,或者发布成一个 Windows 的可执行程序。
1、生成可执行的 Python 档案包
zipapp 是一个可以直接运行的模块,该模块用于将单个 Python 文件或整个目录下的所有文件打包成可执行的档案包。命令行语法如下:
python -m zipapp source [options]
source 参数是要打包的 Python 源程序或目录。如果source参数是目录,则 zipapp 模块会打包该文件夹中的所有 Python 文件。options 参数提供的选项如下:
-o <output>, --output=<output>
:指定输出档案包的文件名,如果不指定,则使用默认文件名,默认是 source 参数值加上 .pyz 后缀。-p<interpreter>, --python=<interpreter>
:指定 Python 解释器-m <mainfn>, --main=<mainfn>
:指定入口函数。该选项为 pkg.mod:fn 形式,其中 pkg.mod 是一个档案包中的包或模块,fn 是指定模块中的函数。如果不指定该选项,则默认从模块中的__main__.py
文件开始执行。-c, --compress
:从 Python 3.7 开始支持该选项,指定档案包进行压缩来减小文件的大小,默认是不压缩。--info
:在诊断时显示档案包中的解释器。-h, --help
:显示 zipapp 模块的帮助信息。
zipapp 使用示例:创建一个 app 子目录,该子目录下可以有多个 Python 源文件,在该目录下的第一个源文件是 say_hello.py,代码如下:
def say_hello(name):
return name + ",您好!"
第二个源文件是:app.py,用来使用 say_hello 模块,代码如下:
from sys import argv
from say_hello import *
def main():
print('开始执行程序')
for arg in argv[1:]:
print(say_hello(arg))
回到 app 子目录的上一级目录,在命令行下执行下面的命令:
python -m zipapp app -o first.pyz -m "app:main"
执行上面命令后,app 子目录下的所有 Python 源文件都会打包成一个档案包,-o 选项指定的就是档案包的文件名;-m 选项指定使用 app.py 模块中的 main 函数作为程序入口。此时在当前目录会生成一个 first.pyz 文件,可使用 Python 命令来运行该文件。示例如下:
> python first.pyz michael tom
开始执行程序
michael,您好!
tom,您好!
在执行打包命令时,如果不指定 -o 参数,则默认输出的文件名是 source 参数值加上 .pyz后缀组成,例如:
python -m zipapp app -m "app:main"
此时会在当前目录下生成 app.pyz 文件。
2、创建独立应用
为了创建能够独立启动的应用(自带依赖模块和包),需要执行两步操作:
第1步:将应用依赖的模块和包下载到应用目录中。
第2步:使用 zipapp 将应用和依赖模块一起打包成档案包。
使用 zipapp 创建独立应用示例:创建 dbapp 子目录作为本应用的目录,该目录下的第一个 Python 源文件是 exec_select.py 文件,该源文件代码如下:
import mysql.connector
# 将执行代码封装到 query_db 函数中
def query_db():
# 第1步:连接 MySQL 数据库,需要提供服务器IP地址、数据库端口号、数据库用户名和密码,以及数据库名称
conn = mysql.connector.connect(user='michael', password='michael123', host='192.168.64.50',
port='3508', database='python', use_unicode=True)
conn.autocommit = True
# 第2步:获取游标
c = conn.cursor()
# 第3步:调用游标的 execute() 方法执行 select 查询语句
c.execute('select * from user_tb where user_id > %s', (4,))
# 通过游标的 description 属性获取列字段信息
for col in (c.description):
print(col[0], end='\t')
print('\n-------------------------------')
# 直接使用 for 循环遍历游标中的结果集
for row in c:
print(row)
print(row[1] + '-->' + row[2])
# 第4步:关闭游标
c.close()
# 第5步:关闭连接
conn.close()
exec_select.py 文件的代码主要是查询 MySQL 数据库中的数据,将主要的执行代码都封装到 query_db() 函数中。
在 dbapp 目录下的第二个 Python 源文件是 __main__.py
,这个文件作为程序入口,这样在打包档案时就不需要指定程序入口。该文件的代码如下:
from exec_select import *
# 执行 query_db() 函数
query_db()
接下来按照下面3步将 dbapp 子目录下的应用打包成独立应用:
第1步:通过命令行工具在 dbapp 所在的目录执行下面命令:
python -m pip install -r requirements.txt --target dbapp
上面的命令就是在使用 pip 模块来安装模块,平时使用 pip 安装模块提示 pip 错误时,也可以使用 python -m pip install
来安装模块。--target
选项是将模块安装到指定目录下,这里指定的是 dbapp 子目录下。-r
选项指定要安装哪些模块,这里使用 requirements.txt 文件列出要安装的模块和包。
-r
选项后面可以直接指定要安装的模块和包,也可使用清单文件指定要安装的模块和包。
如果应用依赖的模块较多,建议使用清单文件来列出所依赖的模块。为了执行上面的命令,需要提前在当前目录下准备好 requirements.txt 文件,该文件中的内容就一行:
mysql-connector-python
这个 requirements.txt 文件的每一行代表一个模块,如果有多个依赖模块,就在这个文件中添加多个模块名的行。执行上面的命令,就开始安装 mysql-connection-python 模块。完成后可以在 dbapp 子目录下看到大量有关 mysql-connection-python 模块的文件。
第2步:如果 pip 在 dbapp 子目录下生成了 .dist-info 目录,可以删除该目录。
第3步:使用 zipapp 模块执行打包操作,这次有了 __main__.py
文件,该文件会作为程序入口,因此在打包时不需要指定 -m 选项。打包命令如下:
python -m zipapp dbapp
此时会在当前目录得到一个 dbapp.pyz 的档案包,该档案包约 20MB,因其包含了 myql-connector-python 模块。
现在,只要目标机器上有合适的 Python 解释器,即可运行该独立应用。可先将本机上的 myql-connector-python 卸载进行测试。卸载命令是:
pip uninstall myql-connector-python
二、使用 PyInstaller 生成可执行程序
1、安装 PyInstaller
PyInstaller 模块需要自行安装,安装命令如下:
pip install pyinstaller
由于该模块还依赖其他模块,所以尽量不要采用离线包方式安装。若成功安装,可以在安装界面看到类似下面的信息:
Successfully installed pyinstaller-3.6
其中的 3.6 之类的数字,代表 PyInstaller 的版本号。此时,在Python 安装目录下的 Script 目录下也会增加一个 pyinstaller.exe 程序。使用该工具可将 Python 程序生成 EXE 程序。
2、生成可执行程序
PyInstaller 工具的命令语法如下:
pyinstaller 选项 Python源文件
不管这个 Python 应用是单文件的应用,压是多文件的应用, 只要在使用 pyinstaller 命令时编译作为程序入口的Python 程序即可。
为了进行示例,先将前面的 app.py 文件略做修改,将该文件改成可执行的 Python 程序。代码如下:
from sys import argv
from say_hello import *
def main():
print('开始执行程序')
if len(argv[1:]) >= 1:
for arg in argv[1:]:
print(say_hello(arg))
else:
print(say_hello('michael'))
# 增加调用 main() 函数
if __name__ == '__main__':
main()
接下来使用命令行工具进入到 app 目录下,在该目录下执行下面命令:
pyinstaller -F app.py
执行上面命令,可以看到详细的生成过程。生成完成后,在app目录下有一个 dist 目录,在该目录下有一个 app.exe 文件,这就是用 PyInstaller 工具生成的 EXE 程序。
在命令行窗口中进入到 dist 目录,即可执行 app.exe 程序,示例如下:
...app\dist> .\app.exe tom jack
开始执行程序
tom,您好!
jack,您好!
需要注意的是,这个程序没有图形界面,如果双击 app.exe 来运行程序,会看到窗口一闪就消失,这样也看不到程序输出结果。
另外,pyinstaller 的 -F 选项是指定生成单独的 EXE 文件,生成的文件在 dist 目录下。在 Mac OS X 平台上生成的文件不带 .exe 后缀。与 -F 选项对应的是 -D 选项(默认选项),该选项指定生成一个目录(包含多个文件)来作为程序。
下面使用 -D 选项进行示例。先将 PyInstaller 工具在 app 目录下生成的 build、dist 目录删除,将 app.spec 文件删除。然后在app目录使用下面命令生成 EXE 文件:
pyinstaller -D app.py
执行这个命令,同样可以看到详细的生成过程。生成完成后,在当前目录下多出一个 dist 目录,在 dist 目录下有一个 app 子目录,在该子目录下包含了大量的 .dll 文件和 .pyz 文件,这些都是 app.exe 程序的支撑文件。在命令行窗口中运行 app.exe 程序,同样可以正常输出。
PyInstaller 不仅支持 -F、-D 选项,还支持其他选项,支持的常用选项如下表所示:
选项 | 作用 |
---|---|
-h, --help | 查看该模块的帮助信息 |
-F, --onefile | 产生单个的可执行文件 |
-D, --onedir | 产生一个目录(包含多个文件)作为可执行程序 |
-a, --ascii | 不包含 Unicode 字符集支持 |
-d, --debug | 产生 debug 版本的可执行文件 |
-w, --windowed, --noconsole | 指定程序运行时不显示命令行窗口(仅对 windows 有效) |
-c, --nowindowed, --console | 指定使用命令行窗口运行程序(仅对 windows 有效) |
-o DIR, --out=DIR | 指定 spec 文件的生成目录。如果没有指定,则默认使用当前目录来生成 spec 文件 |
-p DIR, --path=DIR | 设置 Python 导入模块的路径(和设置PYTHONPATH环境变量的作用相似),也可使用路径分隔符(Windows用分号,Linux用冒号)来分隔多个路径 |
-n NAME, --name=NAME | 指定项目(产生的spec)名字。如果省略,那么第一个脚本的主文件名将作为 spec 的名字 |
PyInstaller 的选项不止上表这些,可以使用 -h 选项查看 PyInstaller 选项的详细信息。
下面使用 PyInstaller 创建一个带图形用户界面,可以访问 MySQL 数据库的应用程序。为此,新建一个 dbapp 目录,将前面创建的 exec_select.py 文件和 __main__.py
拷贝到新建的 dbapp 目录,在该目录下执行下面的命令:
pyinstaller -F -w __main__.py
上面命令中,-F 选项生成单个可执行文件,-w 选项指定生成图形用户界面程序。现在在 dist 子目录下找到 __main__.exe
文件,双击该文件即可运行该程序。
小结:
- Python 的两种打包工具:zipapp 和 PyInstaller。
- zipapp 将文件打包成一个 .pyz 文件,该文件需要 Python 环境来执行。
- PyInstaller 直接打包成可执行程序,该工具还是跨平台,使用也很方便。使用该工具打包的程序,可以分发到对应平台的目标机器上直接运行,无须在目标机器上安装 Python 解释器环境。