Python 脚本打包成可执行文件
Nuitka 目前 (2024.3.16) 最高只支持到 Python 3.11.x,而且实测中对于高版本的 numpy,PyInstaller 和 Nuitka 都不支持(会出现导入错误)。因此这里使用的是 numpy = "1.24.1"
。
背景:最近有个需求涉及科学计算,使用了 Python 的 Numpy 和 Scipy。然后使用了 Next.js + Ant Design 作为前端(UI),后端用 FastAPI 提供计算。最终交付给用户时肯定是不希望用户去装 Python 环境,加上可能需要对一些内部算法进行保密,因此需要打包成可执行程序。
PyInstaller
PyInstaller 可以打包 Python 程序和它依赖到单个包。用户使用的时候就不需要安装 Python 解释器和其它模块。
最简单的使用就是,安装完直接对脚本进行打包:
1 | pip install -U pyinstaller |
默认情况下是打包到一个文件夹里的,好处是依赖很清晰,而且如果依赖没有改变,后续更新代码后只需要更新对应的代码的可执行文件,而不需要更新整个打包。
打包成一个单独的 exe 的好处是非常方便,只有一个 exe。通常来说,单独一个 exe 也往往比一个文件夹的东西小。
内部的实现
PyInstaller 会分析你的脚本,然后得到脚本运行时依赖的各个模块(库),然后把这些依赖连同 Python 解释器拷贝到一个文件夹里,也可以直接打包在一个 exe 里。
PyInstaller 会分析 import
的语句,找到所依赖的模块。但是有一些使用类似 __import__()
、importlib.import_module()
或者 sys.path
在代码中引入的模块是没办法自动被识别的。这种情况需要额外指明这些依赖。
Nuitka
Nuitka 应该说并不是专门用于打包 Python 脚本的。Nuitka 是一个用 Python 写的(written in Python) Python 编译器。编译之后可以不需要分开的 Python 解释器。
目前只支持到 3.11,还不支持 3.12。
使用 Nuitka 相对 PyInstaller 需要的环境会更加复杂一些,额外需要一个 C 的编译器。但如果安装过 Visual Studio(不是 Visual Studio Code),一般就可以了。当然 MinGW64 也是可以的。
最基础的用法和 PyInstaller 差不多:
1 | python -m pip install nuitka |
由于 Nuitka 需要重新编译依赖,实测上打包速度是比较慢的。
数据文件
如果需要额外的附加数据文件,比如静态网页。想要在打包时自动拷贝到文件夹下,而不是手动拷贝。在 PyInstaller 中可以使用,--add-data
。
--add-data
的格式是source:dest
,提供需要拷贝的路径和目标路径
图标和基础信息
pyinstaller 附加图标只需要使用 -i
,例如:pyinstaller -i "gu.ico" ×××.py
Specfile
PyInstaller 除了可以使用基础的命令行进行打包,也可以直接通过 specfile 更直观的定制生成。其实,即使使用命令行进行打包,也会生成 .spec
文件的。
下面不加任何指定命令生成的 .spec
文件。
1 | # -*- mode: python ; coding: utf-8 -*- |