python 加密项目后使用 PyInstaller 打包指南
为什么选择 PyInstaller?
PyInstaller 是一个强大的 Python 打包工具,它可以将 Python 应用程序及其依赖项打包成独立的可执行文件,无需安装 Python 解释器即可运行。对于 MuseTalk 加密项目,使用 PyInstaller 打包有以下优势:
- 简化部署:打包后只需分发一个可执行文件,无需担心目标环境的 Python 版本和依赖问题
- 增强安全性:结合已有的 PyArmor 加密措施,进一步保护代码安全性
- 跨平台支持:可在 Windows、macOS 和 Linux 上使用
- 定制性强:通过 spec 文件可以精细控制打包过程
环境准备
1. 安装 PyInstaller
pip install pyinstaller
2. 确认项目依赖
确保目标环境已安装项目所有依赖:
pip install -r requirements.txt
项目结构分析
在开始打包前,我们需要了解项目的目录结构,这是已经加密后的项目目录:
navtalk-5090-windows/
├── .venv/ # 虚拟环境
├── musetalk/ # 加密后的核心代码
├── pyarmor_runtime_000000/ # PyArmor 运行时
├── scripts/ # 脚本文件
├── utils/ # 工具类
├── .env # 环境配置文件
├── app.py # 主应用入口
├── app_realtime.py # 实时应用
├── app_service.py # 服务应用
├── avatar_api.py # 头像 API
├── engine.py # 引擎
├── pytransform.py # PyArmor 转换模块
└── 其他必要的模块文件
打包步骤
步骤 1:确认项目目录
确保在正确的项目目录中,例如:
cd C:\Users\Admin003\Desktop\pyinstaller\navtalk-5090-windows
步骤 2:创建 PyInstaller 配置文件
在项目根目录中创建 musetalk.spec 文件,这是 PyInstaller 的配置文件,用于控制打包过程:
# -*- mode: python ; coding: utf-8 -*-
import sys
# 增加递归深度限制,避免打包时出现递归错误
sys.setrecursionlimit(sys.getrecursionlimit() * 50)
import os
from PyInstaller.building.build_main import Analysis, PYZ, EXE, COLLECT
# 当前目录(项目根目录)
base_dir = os.path.abspath('.')
# 入口点文件
entry_point = 'app.py'
# 分析阶段
analysis = Analysis(
[entry_point],
pathex=[base_dir],
binaries=[],
datas=[
# 包含.env文件
('.env', '.'), # 当前目录的.env文件
# 包含musetalk目录(加密后的核心代码)
('musetalk', 'musetalk'),
# 包含PyArmor运行时
('pyarmor_runtime_000000', 'pyarmor_runtime_000000'),
# 包含scripts目录
('scripts', 'scripts'),
# 包含utils目录
('utils', 'utils'),
# 包含其他必要的目录
# ('models', 'models'),
('results', 'results'),
('uploads', 'uploads'),
('video', 'video'),
],
hiddenimports=[
'websocket',
'gputil',
'diffusers',
'accelerate',
'numpy',
'tensorflow',
'tensorboard',
'cv2',
'soundfile',
'transformers',
'huggingface_hub',
'librosa',
'einops',
'gradio',
'gdown',
'requests',
'imageio',
'omegaconf',
'ffmpeg',
'moviepy',
'aiohttp_socks',
'webrtcvad',
'scipy',
'torch.testing', # 必须包含,否则会导致运行时错误
# Flask 相关依赖
'flask',
'flask_cors',
# 其他可能需要的依赖
'websocket_client',
'ffmpeg_python',
'imageio_ffmpeg',
],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=None,
noarchive=False,
)
# PYZ阶段
pyz = PYZ(analysis.pure, analysis.zipped_data, cipher=None)
# EXE阶段
executable = EXE(
pyz,
analysis.scripts,
analysis.binaries,
analysis.zipfiles,
analysis.datas,
[],
name='musetalk',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=False, # 禁用UPX压缩,避免struct.error错误
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
# COLLECT阶段(创建单文件夹部署)
collect = COLLECT(
executable,
analysis.binaries,
analysis.zipfiles,
analysis.datas,
strip=False,
upx=False, # 禁用UPX压缩,避免struct.error错误
upx_exclude=[],
name='musetalk',
)
步骤 3:执行打包命令
在项目根目录中执行以下命令开始打包:
# 使用虚拟环境中的PyInstaller
.venv\Scripts\pyinstaller.exe musetalk.spec
# 或使用系统安装的PyInstaller
pyinstaller musetalk.spec
打包过程可能需要几分钟时间,取决于项目大小和系统性能。
步骤 4:验证打包结果
打包完成后,PyInstaller 会在项目目录中生成一个新的 dist 目录,包含:
musetalk/目录:包含打包后的应用musetalk.exe:主可执行文件(Windows)- 相关依赖文件和目录
步骤 5:外部挂载模型文件
如果排除了 models 目录(因为它太大),可以通过以下方法在外部挂载模型文件:
方法 1:修改 .env 文件配置
-
在打包后的
dist目录中找到.env文件 -
添加或修改以下配置,指向外部模型目录:
# 模型路径配置 MODELS_DIR=D:/path/to/external/models -
修改应用代码以使用这个环境变量(如果尚未支持):
# 在 gpu_model_manager.py 中 import os models_dir = os.getenv('MODELS_DIR', './models') unet_model_path = os.path.join(models_dir, 'musetalkV15', 'unet.pth') unet_config = os.path.join(models_dir, 'musetalkV15', 'musetalk.json')
方法 2:创建符号链接
在 Windows 上,使用管理员权限运行命令提示符:
mklink /D "dist\musetalk\models" "D:\path\to\external\models"
在 Linux/macOS 上:
ln -s "D:/path/to/external/models" "dist/musetalk/models"
方法 3:直接复制模型文件
将外部模型文件直接复制到打包后的 dist/musetalk/models 目录中。
步骤 6:启动应用
在目标系统上,运行以下命令启动服务:
# Windows
dist\musetalk\musetalk.exe
# Linux/macOS
./dist/musetalk/musetalk
配置说明
spec 文件关键参数解析
-
datas:指定需要包含的非代码文件,格式为
(源路径, 目标路径)- 例如:
('.env', '.')表示将当前目录的.env文件复制到打包后的根目录 - 确保包含
pyarmor_runtime_000000目录,这是 PyArmor 加密运行时所必需的
- 例如:
-
hiddenimports:指定需要包含的隐藏导入模块
- 这些模块可能没有被直接导入,但在运行时需要使用
-
upx:是否使用 UPX 压缩可执行文件
- 设置为
True可以减小可执行文件大小
- 设置为
-
console:是否显示控制台窗口
- 设置为
True可以查看运行时输出和错误信息
- 设置为
常见问题与解决方案
问题 1:找不到 .env 文件
错误信息:
ERROR: Unable to find 'C:\Users\Admin003\Desktop\pyinstaller\.env' when adding binary and data files.
解决方案:
确保 .env 文件存在于正确的位置,并且在 datas 配置中使用正确的相对路径:
datas=[
('.env', '.'), # 当前目录的.env文件
# 其他文件...
]
问题 2:PyArmor 运行时错误
错误信息:
ModuleNotFoundError: No module named 'pyarmor_runtime_000000'
解决方案:
确保在 datas 配置中包含了 pyarmor_runtime_000000 目录:
datas=[
('pyarmor_runtime_000000', 'pyarmor_runtime_000000'),
# 其他文件...
]
问题 3:打包后缺少依赖模块
错误信息:
ModuleNotFoundError: No module named 'xxx'
解决方案:
在 hiddenimports 列表中添加缺少的模块。
问题 4:PyInstaller 命令未找到
错误信息:
'pyinstaller' 不是内部或外部命令,也不是可运行的程序或批处理文件。
解决方案:
使用完整路径运行 PyInstaller:
.venv\Scripts\pyinstaller.exe musetalk.spec
问题 5:打包后可执行文件过大
解决方案:
- 确保使用了
upx=True启用压缩 - 检查是否包含了不必要的文件和目录
- 考虑使用
--onefile选项创建单个可执行文件
问题 6:目录不存在错误
错误信息:
ERROR: Unable to find 'path/to/directory' when adding binary and data files.
解决方案:
检查 datas 配置中指定的目录是否存在,如果不存在,移除或注释掉相关配置:
datas=[
('.env', '.'),
('musetalk', 'musetalk'),
('pyarmor_runtime_000000', 'pyarmor_runtime_000000'),
# 只添加实际存在的目录
# ('models', 'models'), # 如果不存在,注释掉
# ('results', 'results'), # 如果不存在,注释掉
]
问题 7:递归深度超出错误
错误信息:
A RecursionError (maximum recursion depth exceeded) occurred.
解决方案:
-
在 spec 文件顶部添加以下代码,增加递归深度限制:
import sys sys.setrecursionlimit(sys.getrecursionlimit() * 5) -
重新执行打包命令:
.venv\Scripts\pyinstaller.exe musetalk.spec -
如果仍然失败,尝试排除不必要的测试模块:
excludes=['torch.testing', 'expecttest'], # 排除测试模块
问题 8:struct.error: argument out of range 错误
错误信息:
struct.error: argument out of range
解决方案:
- 禁用 UPX 压缩:修改 spec 文件,禁用 UPX 压缩:
# EXE阶段
executable = EXE(
pyz,
analysis.scripts,
analysis.binaries,
analysis.zipfiles,
analysis.datas,
[],
name='musetalk',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=False, # 禁用UPX压缩
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
COLLECT阶段
collect = COLLECT(
executable,
analysis.binaries,
analysis.zipfiles,
analysis.datas,
strip=False,
upx=False, # 禁用UPX压缩
upx_exclude=[],
name='musetalk',
)
2. **排除不必要的依赖**:在 spec 文件中添加 excludes 参数:
```python
analysis = Analysis(
[entry_point],
pathex=[base_dir],
binaries=[],
datas=[
# 现有配置...
],
hiddenimports=[
# 现有配置...
],
hookspath=[],
runtime_hooks=[],
excludes=[
'torch.testing',
'expecttest',
'tensorflow',
'tensorboard',
'pytest',
'unittest',
],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=None,
noarchive=False,
)
- 清理临时文件:删除 build 和 dist 目录,重新执行打包命令。
部署与使用
步骤 1:分发打包结果
将 dist/musetalk 目录复制到目标服务器。
步骤 2:配置环境
-
确保目标系统满足以下要求:
- 与打包时相同的操作系统类型
- 足够的磁盘空间和内存
-
检查
.env文件配置,根据目标环境修改相关路径和参数。 -
配置外部模型路径(如果排除了 models 目录):
- 参考前面的「步骤 5:外部挂载模型文件」部分
- 选择适合您环境的方法来配置模型路径
步骤 3:启动服务
在目标系统上,运行以下命令启动服务:
# Windows
dist\musetalk\musetalk.exe
# Linux/macOS
./dist/musetalk/musetalk
步骤 4:验证服务
- 查看控制台输出,确认服务是否成功启动
- 通过配置的端口(默认 40001)访问服务
- 测试核心功能是否正常运行
- 验证模型是否正确加载(如果使用外部模型)
高级技巧
1. 创建单个可执行文件
如果希望生成单个可执行文件而不是目录,可以修改 spec 文件:
# 移除 COLLECT 阶段,直接使用 EXE 阶段
executable = EXE(
pyz,
analysis.scripts,
analysis.binaries,
analysis.zipfiles,
analysis.datas,
[],
name='musetalk',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
onefile=True, # 添加这一行
)
2. 自定义图标
可以为可执行文件添加自定义图标:
executable = EXE(
# 其他参数不变
icon='path/to/icon.ico', # 添加图标路径
)
3. 排除不必要的模块
可以通过 excludes 参数排除不必要的模块,减小可执行文件大小:
analysis = Analysis(
# 其他参数不变
excludes=['tkinter', 'unittest', 'pydoc'], # 排除不需要的模块
)
4. 条件包含目录
修改 spec 文件,使用条件判断来包含存在的目录,避免因目录不存在而导致的错误:
import os
datas = [
('.env', '.'),
('pyarmor_runtime_000000', 'pyarmor_runtime_000000'),
]
# 条件包含存在的目录
directories = ['musetalk', 'scripts', 'utils', 'models', 'results', 'uploads', 'video']
for dir_name in directories:
if os.path.exists(dir_name):
datas.append((dir_name, dir_name))
print(f"包含目录: {dir_name}")
else:
print(f"跳过不存在的目录: {dir_name}")
# 然后在 Analysis 中使用 datas 变量
analysis = Analysis(
[entry_point],
pathex=[base_dir],
binaries=[],
datas=datas,
# 其他参数不变
)
总结
使用 PyInstaller 打包 MuseTalk 加密项目可以大大简化部署过程,确保项目在不同环境中稳定运行。通过本文的步骤,您可以:
- 成功打包已经加密后的 MuseTalk 项目
- 包含所有必要的文件和依赖,包括 PyArmor 运行时
- 解决打包过程中可能遇到的常见问题
- 有效地部署和使用打包后的应用
这种打包方式特别适合已经使用 PyArmor 加密的项目,可以在保护代码安全的同时,提供便捷的部署体验。
附录:完整命令清单
1. 确认项目目录并创建 spec 文件
cd C:\Users\Admin003\Desktop\pyinstaller\navtalk-5090-windows
# 创建 musetalk.spec 文件(内容如上)
2. 执行打包命令
# 使用虚拟环境中的 PyInstaller
.venv\Scripts\pyinstaller.exe musetalk.spec
# 或使用系统 PyInstaller
pyinstaller musetalk.spec
3. 启动命令
# Windows
dist\musetalk\musetalk.exe
# Linux/macOS
./dist/musetalk/musetalk
注意:本文档适用于 MuseTalk 加密项目的打包,其他使用 PyArmor 加密的项目可以参考此方法进行调整。打包过程中遇到的具体问题可能因环境差异而有所不同,请根据实际情况进行调整。
- 感谢你赐予我前进的力量

