1. Python 编译为 pyc 文件 @
1.1 基本编译方法 @
pyc 文件是 Python 的字节码编译文件,能够提高模块加载速度并保护源代码。
# Python3 源码目录编译 pyc
# -b 参数表示在 legacy 模式下生成 pyc 文件(不带 Python 版本号)
python -m compileall -b .
# Python2 源码目录编译 pyc
python -m compileall .
1.2 清理与优化 @
编译完成后,需要进行文件清理以保持目录整洁:
# 删除 Python 缓存目录
find . -name '__pycache__' -exec rm -rf {} \;
# 选择性删除源文件(谨慎操作)
# 注意:此操作不可逆,建议先备份
find . -name '*.py' -type f -exec rm -rf {} \;
注意事项:
- pyc 文件与 Python 版本相关,不同版本可能不兼容
- 删除源文件前务必确认 pyc 文件能正常工作
- 建议在生产环境中保留源文件备份
2. PyInstaller 打包为二进制可执行文件 @
2.1 基本打包流程 @
PyInstaller 能够将 Python 程序及其依赖打包成独立的可执行文件。
# 安装 PyInstaller
pip install pyinstaller
# 基本打包命令
# -F: 打包成单个可执行文件
# -w: 窗口模式(不显示控制台,适用于 GUI 程序)
pyinstaller -F -w xxxxx.py
2.2 处理依赖问题 @
当遇到模块导入错误时,需要显式指定隐藏导入:
# 处理 queue 模块导入问题
pyinstaller -F -w xxxxx.py --hidden-import=queue
2.3 加密保护 @
PyInstaller 支持对字节码进行加密,保护源代码:
# 安装加密支持
pip install pyinstaller[encryption]
# 生成加密密钥(16 字符)
openssl rand -base64 16 | cut -c1-16
# 使用加密打包
pyinstaller -F -w xxxxx.py --key=生成的密钥字符串
2.4 平台兼容性问题 @
libc.so 依赖问题:
- 向后兼容性:低版本 Linux 打包的程序可在高版本运行
- 向前不兼容:高版本打包的程序无法在低版本运行
- Alpine Linux:使用 musl libc,与常规发行版的 glibc 不兼容
推荐方案:
- 使用 CentOS 7 或 Ubuntu 16.04 等较老发行版进行打包
- 避免在 Alpine Linux 环境下打包用于其他发行版的程序
2.5 常见问题修复 @
问题描述:
在 depend/utils.py 第 402 行,缺少匹配检查导致异常。
问题代码:
for line in text: # 注意:此假设库名不包含空格
m = pattern.match(line)
path = m.groups()[-1] # 当 m 为 None 时会抛出异常
修复方案:
for line in text:
m = pattern.match(line)
if m is None: # 添加空值检查
continue
path = m.groups()[-1]
参考链接: PyInstaller Issue #5540
3. Cython 编译优化 @
3.1 环境准备 @
Cython 将 Python 代码编译为 C 代码,需要安装开发依赖:
# CentOS/RHEL 系统
yum install python-devel
# Ubuntu/Debian 系统
apt-get install python-dev
# 安装 Cython
pip install Cython
3.2 编译为可执行文件 @
# 生成嵌入式的 C 文件
cython --embed xxxxx.py
# 使用 GCC 编译
gcc -L /usr/lib/python3.8/ \
-I /usr/include/python3.8/ \
-o rule_cfg_fix rule_cfg_fix.c \
-lpython3.8 -lpthread -lm -lutil -ldl
参数说明:
-
-L: 指定 Python 库文件路径 -
-I: 指定 Python 头文件路径 -
-o: 指定输出文件名 -
-l: 链接所需的动态库
3.3 编译为共享库 (.so 文件) @
创建 setup.py 配置文件:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [
Extension("hello_world", # 模块名
["hello_world.pyx"]) # 源文件
]
)
执行编译:
# 生成 .so 共享库文件
python setup.py build_ext --inplace
编译结果:
- 生成
hello_world.so文件 - 可在 Python 中直接导入使用:
import hello_world
4. 方案对比与选择建议 @
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| pyc 编译 | 简单快速,提高加载速度 | 源码仍可反编译,保护性弱 | 加速模块加载,基础保护 |
| PyInstaller | 完全独立,跨平台支持 | 文件体积大,libc 依赖问题 | 分发独立应用程序 |
| Cython | 性能优化好,保护性强 | 编译复杂,调试困难 | 性能关键模块,代码保护 |
选择建议:
- 快速部署:使用 pyc 编译
- 独立分发:选择 PyInstaller
- 性能优化:采用 Cython 编译
- 商业保护:结合 PyInstaller 加密和 Cython
通过合理选择编译方案,可以有效保护 Python 代码知识产权,提升程序性能,并简化部署流程。