
PyInstaller 生成的 .pyz 文件名仅是命名习惯,实际产物是平台相关的原生可执行文件(如 Linux ELF),并非 Python 官方定义的、可跨平台运行的 ZIP-based 可执行模块(PEP 441 .pyz)。在 macOS 上直接 python3 xxx.pyz 运行必然失败,并触发编码解析异常。
pyinstaller 生成的 `.pyz` 文件名仅是命名习惯,实际产物是平台相关的**原生可执行文件**(如 linux elf),并非 python 官方定义的、可跨平台运行的 zip-based 可执行模块(pep 441 `.pyz`)。在 macos 上直接 `python3 xxx.pyz` 运行必然失败,并触发编码解析异常。
你遇到的 SyntaxError: Non-UTF-8 code starting with '\xb9' 错误,根本原因在于:你正试图用 Python 解释器去执行一个二进制可执行文件——而该文件头部包含非 UTF-8 字节(如 \xb9,常见于 x86 指令或 ELF 文件魔数),Python 在尝试按源码方式读取并解码第 2 行时崩溃。
这与文件头声明的编码(如 # -*- coding: utf-8 -*-)或 PYTHONIOENCODING 环境变量完全无关,因为问题不发生在你的源码解析阶段,而发生在对非法“伪 Python 源文件”的误读上。
✅ 正确认知:
- ✅ PyInstaller 的
--onefile模式产出的是平台专属可执行程序(Linux 上为 ELF,macOS 上为 Mach-O,Windows 上为 PE); - ❌ 它不是 PEP 441 定义的
.pyz格式(即 ZIP 归档 +__main__.py+python -m zipapp兼容格式); - ❌ 因此不可跨平台运行,也不能通过
python3 xxx.pyz启动(该命令仅适用于真正的 ZIP-based.pyz)。
? 验证方法(在 Ubuntu 构建后):
# 查看文件真实类型(非扩展名) file build/pyz/test_pyz # 输出示例:test_pyz: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), ...
? 正确使用方式:
- 在 Ubuntu 容器中构建 → 在 Ubuntu 环境中直接运行
./build/pyz/test_pyz(需chmod +x); - 如需 macOS 兼容版本,必须在 macOS 主机或 macOS CI 环境中重新运行 PyInstaller 构建(不能复用 Linux 产物);
- 若目标是真正跨平台的
.pyz,应改用标准工具链:# 创建符合 PEP 441 的可执行 ZIP python -m zipapp myapp/ -m "myapp.__main__:main" -o myapp.pyz # 此时可在任何安装了对应 Python 版本的系统上运行: python3 myapp.pyz
⚠️ 注意事项:
- 不要混淆
pyinstaller --onefile和python -m zipapp的语义与产物; - Poetry 的
poetry run pyinstaller仅是调用封装,不改变 PyInstaller 的底层行为; -
.spec文件中的# -*- coding: utf-8 -*-仅影响.spec自身的 Python 解析,与最终可执行文件的编码无关; - 若项目需多平台分发,建议采用 GitHub Actions 分别为
ubuntu-latest、macos-latest、windows-latest设置独立构建作业。
总结:这不是编码配置问题,而是概念性误用。修正路径是——明确构建目标(平台专用可执行 vs 跨平台 ZIP 应用),选择对应工具,并严格遵循平台隔离原则。










