前面我们完成了很多使用 Python 开发的工具,我都是直接在 PyCharm 中演示的运行效果。但使用 Python 源文件传递带来一个问题,换一台电脑就需要重新安装依赖库,不利于代码维护。并且程序在不完善交互功能的情况下给使用者会带来很多麻烦。
所以把 Python 原文件打包编译成 exe 文件,并完善交互功能,是最好的保存、传递程序的办法。所以这一期,我简单介绍下 Python 文件的打包方法。
本期目录
1. 为什么需要源文件打包
2. 主流打包工具
3. PyInstaller 标准打包流程
4. 常见问题:如何解决“打包后文件太大”
5. 总结
上面我们已经提到 Python 代码编译成 exe 文件的必要,举个很简单的例子,你完成了一个 Python 程序,在自己电脑上完美运行。但如果你将源码发送给别人使用,在他的电脑上运行源码,最大概率出现的问题就是提示环境配置错误。
对于专业程序员而言,这个问题只是解决起来有点费事。但对于更多非专业的使用者而言,对程序环境配置理解不足,会带来很多困难。
所以,开发者将源代码编译成 exe 非常有必要:
把 Python 脚本打包成 .exe 文件时,会将 Python 解释器、所有依赖的第三方库(如 Numpy、Pandas、Requests)以及你的代码逻辑,像压缩包一样封装进一个独立的可执行文件中。
对于接收者而言,无需安装任何开发环境,双击即用。当然,打包不代表所有环境依赖的问题都能解决,比如操作系统问题,32位与64位系统不通用,win10打包的程序无法在win7系统上顺利使用;一些需要调用第三方安装软件的程序,比如Tesseract OCR、FFmpeg 都需要独立安装。
打包过程会对源代码进行字节码转换,甚至在使用 Nuitka 等工具时可以进行 C++ 编译。虽然不能百分之百防止反编译破解,但相比于直接暴露,大大提高了代码被破解或被随意篡改的门槛。也能提高开发者对代码的可维护性,防止在传递的过程中被改的乱七八糟。
非开发人员在查看代码时,偶尔的一个误触(比如删掉一个缩进或括号)就会导致程序报废。打包后用户无法直接编辑内部代码,保证了程序在使用中的稳定性和一致性。
当然,我觉得对我来说更重要的一点,打包可以将程序“版本化”、“交互化”,可以保证每个 exe 文件都是可以简单双击执行的,也能够很好保存、记录程序的各个版本。
Python 打包工具五花八门,有的胜在通用,有的胜在性能,主流的选择有 PyInstaller、Nuitka 和 Auto-py-to-exe:
PyInstaller 是一个强大的打包工具,用于将 Python 脚本打包成独立的可执行文件,如 .exe 。它支持多种操作系统,并能将所有依赖打包到一个文件中,方便分发和部署。
对于初学者而言,PyInstaller 几乎是必选,它是目前社区支持最广、文档最全的工具。
pip install pyinstaller #安装方式
Nuitka 的工作原理与众不同:它不是简单的“打包”,而是将 Python 代码编译成 C++ 代码,再编译为机器码。这样做的好处是,运行速度有明显提升;安全性极高(因为代码已经变成了二进制机器码,反编译难度极大);生成的 exe 体积通常比 PyInstaller 更小。当然,相对上手门槛稍高,打包过程也非常耗时。
Auto-py-to-exe 是一个基于 Chrome 浏览器界面的开源工具,但它的底层完全调用 PyInstaller,它把枯燥的指令变成了下拉菜单、复选框和文件选择框。你可以理解为,它为 PyInstaller 套上了一个可视化的“图形外壳”,可以使用界面操作,免去了很多写代码的困扰。
pip install auto-py-to-exe #安装方式
安装后在终端内直接输入 auto-py-to-exe 就可以直接弹出打包页面。
其实 PyInstaller 的打包方式还是很简单的,最简单的情况只需要一句代码,一个命令就能实现。但也有一些需要注意的地方:
使用“虚拟环境”是 Python 编程中一个很好的编写习惯。在编译器中新建项目,比如 PyCharm 新建项目注意选择虚拟环境,这样就能避免把各种无关的库全部带进去,也避免程序完成过程中污染全局环境。在虚拟环境下打包程序,就只会打包虚拟环境下安装的库,能大大减小打包程序的体积。
-F # 打包成单个可执行文件-D # 打包成包含多个文件的文件夹-w # 隐藏控制台窗口(适用于 GUI 应用,防止后台跳出黑色命令行窗口)-i # 指定可执行文件的图标(需使用 .ico 格式)-n # 指定生成的可执行文件名称--add-data "源路径;目标路径"# 添加非代码资源(如 Excel 模板、图片、配置文件)--hidden-import 模块名 # 手动补丁:强制添加由于动态调用而被漏掉的依赖模块--collect-all 库名 # 暴力打包:将复杂库(如 OCR、语音识别)的所有组件一并搬运
pyinstaller --onefile --collect-all faster_whisper --collect-all ctranslate2 sound_to-text.py
其中 --onefile 就是 -F,--collect-all 用于强制打包依赖库,主要还是因为语转文模型的底层执行逻辑比较复杂,为了防止换电脑后运行报错,强制把相关文件都打包到 exe 文件中,虽然可能会导致文件臃肿,但能保证运行的顺利。
如果你的脚本需要读取某个 template.xlsx 模板或一张图片,直接打包 -F 会导致程序运行时找不到文件。这时需要告诉 PyInstaller 把这些资源也塞进去:
pyinstaller -F --add-data "data/template.xlsx;data" main.py
这里涉及的内容和技巧很多,我不打算展开讲,简单来说 requirements.txt 一份“环境清单”,记录了项目运行所需的所有第三方库及其精确版本,确保你的代码在不同电脑上能拥有一致的运行表现。
#导出当前程序的依赖库清单pip freeze > requirements.txt #在新环境下批量安装库pip install -r requirements.txt
对于代码上的问题,通过网页和 AI 助手,完全可以处理掉,但我觉得对程序打包后体积过大问题更多是习惯问题,所以我觉得值得注意下:
最常见的情况:一个只有几十行的代码,打包出来的 exe 居然有几百兆。最常见的原因:
①环境污染:你在全局环境下进行打包。PyInstaller 会扫描你电脑里装过的所有库,即使你的脚本没用到,它也可能因为某些隐形的依赖链把整个科学计算包全塞进去。所以,还是那句话,务必养成在虚拟环境下书写代码和打包的习惯。
② 剔除无用模块:某些库(如 numpy 或 pandas)在打包时会默认带入巨大的底层数学加速库,但对于简单的程序,这些库并非必须。操作方法: 在命令中使用 --exclude-module 强制排除不需要的重型模块。
# 排除掉通常体积巨大的绘图或测试库pyinstaller -F --exclude-module matplotlib --exclude-module notebook --exclude-module jedi main.py
③ 使用 Nuitka 进行编译或者其他工具压缩:比如,使用 UPX 对生成的二进制文件进行二次压缩;或者使用 Nuitka 将 Python 代码转换成 C++ 并编译为机器码。虽然以上方法会将文件体积变得更小,但我个人觉得对于工程或者办公开发需要写的一些轻型脚本而言,没有太大必要。
pyinstaller -F --upx-dir"D:/upx_path" main.pynuitka --standalone --onefile --remove-output main.py
这一期主要是介绍了 Python 程序打包成可执行文件的一系列操作方法,特别是一些常用工具、打包方法和常见问题。内容并没有讲太深,但对于我们工程类开发者而言,已经足够了。除了理论上的,还需要各位结合实操中遇到的问题去解决,如果你遇到了什么困难也可以留言或者私信,我们一块探讨。
这一期就到此为止,如果你也对Python编程技巧和应用实例感兴趣,欢迎点赞,收藏,关注,我将以应用案例为基础持续更新公众号文章。你也可以在公众号后台,获取Python编程的经典资料,也可以与我私信交流想法和需求,我们下期再见~