12. 打包和发布
打包发布 Python 程序通常使用的工具有 zipapp
和 PyInstaller
,其中, zipapp
模块可用于生成可执行的 Python 包,这个包会包含目录下所有的 Python 程序,也可以将 Python 程序所依赖的模块下载到目标目录下,再生成可独立运行的 Python 程序,但是这样依旧依赖于 Python 的运行环境。 PyInstaller
工具则是将 Python 程序直接编译成不同平台上的可执行程序,这样就可以脱离 Python 的运行环境直接执行。
12.1. 使用 zipapp 模块
zipapp
是 Python 内置的一个模块,通过该模块可以将一个 Python 模块打包成一个 Python 应用。
12.1.1. 生成可执行的 Python 包
zipapp
模块的命令行语法如下:
python -m zipapp source [options]
其中, source
代表要打包的 Python 源程序或目录,既可以是单个的 Python 文件,也可以是文件夹。如果 source
参数是文件夹,那么 zipapp
模块会打包该文件夹中的所有 Python 文件。 options
支持如下选项:
-o <output>
:指定输出的文件名。如果不指定该选项,所生成的文件名默认为source
的值,并加上.pyz
后缀-p <interpreter>
:指定 Python 解释器-m <mainfunc>
:指定 Python 程序的入口函数-c
:用于指定是否对档案包进行压缩来减小文件的大小,默认不压缩--info
:用于在诊断时显示包中的解释器-h
:用于显示zipapp
模块的帮助信息
在此我们以一个简易的计算器程序为例,介绍 zipapp
模块的使用方法,在文件夹 chapter12
下创建源代码,简易计算器完成 +
, -
,*
, /
, %
的功能,新建 calculate.py
文件,具体代码如下:
def cal(a, b, ops):
if ops == "+":
return a + b
elif ops == "-":
return a - b
elif ops == "*":
return a * b
elif ops == "/":
return a / b
elif ops == "%":
return a % b
else:
# 抛出异常
raise
同时,在该目录下新建一个 app.py
的程序,具体代码如下:
from calculate import *
if __name__ == "__main__":
while True:
try:
a = float(input("请输入:a = "))
b = float(input("请输入:b = "))
ops = input("请输入运算符:")
ret = cal(a, b, ops)
print(str(a) + " " + ops + " " + str(b) + " = " + str(ret))
break
except Exception as e:
print("输入错误,请重新输入。。。")
continue
在命令行工具中进入 chapter12
目录下,并执行如下命令:
python3 -m zipapp app.py -o app.pyz
此时,在 chapter12
目录下生成了一个 app.pyz
文件,通过如下命令执行该程序:
python3 app.pyz
12.1.2. 生成独立应用
上述的打包方式只能打包当前的 Python 文件,对于其中依赖的文件则不能一起打包出来,如上述的 app.py
程序中依赖 calculate.py
的程序,将打包好的 app.pyz
移动到其他任意的文件夹下执行,就会报如下的错误:
Traceback (most recent call last):
File "app.pyz", line 1, in <module>
from calculate import *
ModuleNotFoundError: No module named 'calculate'
这种情况下,我们就需要对所有依赖的程序打包,需要如下的两个步骤:
- 将应用依赖的模块和包下载到同一个目录中
- 使用
zipapp
将应用和依赖模块一起打包
首先需要将所有依赖下载到同一个目录下,对于依赖的第三方库,需要使用到 pip install
语句安装到指定目录下,为做测试,我们在 chapter12
目录下新建一个 app
的文件夹,在 chapter12
新建一个 requirements.txt
的文件,用于填写需要下载的第三方库,此处我们不依赖其他的第三方库,在 chapter12
目录下执行以下命令:
python3 -m pip install -r requirements.txt --target app
此时还需要将所有的文件复制到 app
的文件夹下,此处需要的文件包括 calculate.py
和 app.py
,同时将 app.py
改名为 __main__.py
用于标记程序的入口,在 chapter12
目录下再执行以下命令:
python -m zipapp app -o app.pyz
此时在 chapter12
目录下生成了 app.pyz
文件,将其移动到其他任意文件夹下都可以正常执行了。
12.2. 使用 PyInstaller 生成可执行程序
上述的打包方式依然依赖于 Python 的运行环境,还可以使用 PyInstaller
将 Python 程序生成可直接运行的程序。
12.2.1. PyInstaller 的安装
PyInstaller
模块并不是 Python 的内置模块,需要自行安装。使用 pip
的安装命令如下:
pip install pyinstaller
安装完成后,执行以下的命令以判断是否安装成功:
pyinstaller -V
如果安装成功,会出现如下的信息:
12.2.2. 生成可执行程序
PyInstaller
工具的命令语法如下:
pyinstaller options source
不管这个 Python 应用是单文件的应用,还是多文件的应用,只要在使用 pyinstaller
命令时编译作为程序入口的 Python 程序即可。还是以上述简易计算器代码为例,将 calculate.py
和 __main__.py
复制到文件夹 appinstaller
下,并执行以下的命令:
pyinstaller -D __main__.py
这里以 mac os 为例,等打包完成后就会在 appinstaller
文件夹下生成 __main__.spec
文件和 build
, dist
文件夹,如下图所示:
最终生成的可执行文件在 dist
目录下生成名为 __main__
可执行文件,双击该文件,就可以正常执行,运行结果如下图所示:
至此已经完成了程序的打包,其中, options
参数除了 -D
以外,还有如下的一些可供选择:
12.3. 本章小结
本章主要介绍了两种打包 Python 程序的工具: zipapp
和 PyInstaller
,其中, zipapp
主要用于将 Python 应用打包成一个可运行的 .pyz
文件,但是该文件依然需要 Python 环境来执行。而 PyInstaller
则直接将 Python 程序打包成可执行程序,而无需依赖 Python 环境。
本章需要掌握知识点:
- 掌握
zipapp
的两种打包方式 - 掌握
PyInstaller
打包方法