使用nuitka打包python包为pyd
快速流程
环境准备
python -m pip install nuitka
python -m pip install mypy
生成pyd文件
python -m nuitka --module --output-dir=nuitka_build --include-package=pkgName PkgName
生成pyi文件(递归)
stubgen -p pkgName -o nuitka_build/
详细说明
下面是详细说明用 Nuitka 把一个 Python 包(含子包)编译成单个 .pyd,并为 IDE 生成 .pyi 类型桩以获得完善的自动补全的流程。
一、目标
- 把包
yourpkg编译为一个二进制扩展模块:nuitka_build/yourpkg.cp3xx-<platform>.pyd(Windows下为.pyd,Linux/macOS下为.so)。 - 为该包生成配套的
.pyi类型桩,IDE(PyCharm/VS Code)将有高质量的自动补全与跳转。
二、前置条件
- Python 3.8+(与目标环境一致,位数也要一致,例如都为 x64)。
- 编译器环境:
- Windows:安装
Visual Studio Build Tools(含 MSVC 与 Windows SDK),确保cl在 PATH 中。 - Linux:安装
gcc和必要的构建工具(如build-essential)。 - macOS:安装
Xcode Command Line Tools(xcode-select --install)。
- Windows:安装
- 包必须是合法包:包目录及其子目录需要包含
__init__.py(PEP 420 的命名空间包不建议用于此流程)。 - 建议使用虚拟环境,以减少环境差异。
三、安装工具
- 基本依赖
python -m pip install -U nuitkapython -m pip install -U mypy
- 可选(让 Nuitka 更快/更稳):
python -m pip install orderedset zstandard
四、编译为单个.pyd/.so
- 样例说明
- 假设包的导入名为
yourpkg(目录名同yourpkg/),下面命令从项目根目录执行。
- 假设包的导入名为
- 基本命令
- Windows/Linux/macOS 通用:
python -m nuitka --module yourpkg --include-package=yourpkg --output-dir=nuitka_build
- Windows/Linux/macOS 通用:
- 选项解释
--module:以“扩展模块”模式输出.pyd/.so(而非可执行文件)。--include-package=yourpkg:把 yourpkg 包及其子包编进同一个扩展模块里,支持后续import yourpkg.submod。--output-dir:产物输出目录。
- 常见补充
- 动态导入(
importlib.import_module/字符串拼接)可能被静态分析漏掉,需显式包含:--include-module=yourpkg.submod_a --include-package=yourpkg.plugins
- 如需附带包内的数据文件(json/模型等):
--include-data-files="yourpkg/data/*=yourpkg/data/"- 运行时建议用
importlib.resources或pkgutil.get_data访问相对资源。
- 动态导入(
- 注意
- “模块模式”并不是“独立运行”打包,第三方依赖不会被合并到
.pyd中,它们仍需在运行时可用(pip 安装到环境即可)。 - 输出文件名包含 Python 版本与平台标签,例如
yourpkg.cp311-win_amd64.pyd。
- “模块模式”并不是“独立运行”打包,第三方依赖不会被合并到
五、生成 .pyi 类型桩(递归)
- 推荐从源码生成(保留注解信息更完整)
- 确保
yourpkg可被当前解释器导入(例如在项目根执行:python -m pip install -e .,或将项目根加入PYTHONPATH)。 - 生成:
python -m mypy.stubgen -p yourpkg -o nuitka_build
- 完成后,
nuitka_build下会出现一个yourpkg目录,里面是__init__.pyi与各子模块.pyi。
- 确保
- 如果无法从源码生成(退而求其次)
- 在能 import 到编译产物的环境中执行:
python -m mypy.stubgen -m yourpkg -o nuitka_build
- 这种方式主要依赖运行时反射,类型信息通常较少,优先使用“从源码生成”。
- 在能 import 到编译产物的环境中执行:
六、放置与使用建议
-
目录布局(示例)
nuitka_build/ - yourpkg.cp311-win_amd64.pyd <-- 编译产物 - yourpkg/ <-- 仅包含 .pyi 的“桩包” - __init__.pyi - submod.pyi - utils/__init__.pyi -
为什么这样放
yourpkg.pyd(扩展模块)提供实际运行实现。- 旁边的
yourpkg/(只有.pyi,没有.py)只被类型检查器/IDE读取,不会影响运行时导入顺序。 - Python 导入
yourpkg时会选择.pyd作为实现;IDE 会优先读取.pyi进行补全与类型推断。
-
测试导入
- 在干净虚拟环境中,把
nuitka_build加入sys.path(或复制到site-packages):- 交互式测试:
PYTHONPATH=./nuitka_build python -c "import yourpkg, yourpkg.submod; print('OK')"
- 交互式测试:
- 在 PyCharm 中将
nuitka_build标记为Source Root,或把它安装到解释器的site-packages中。
- 在干净虚拟环境中,把
七、常见问题排查
- 找不到编译器(cl/gcc/clang)
- Windows:安装
VS Build Tools,用x64 Native Tools Command Prompt for VS执行命令。 - Linux/macOS:安装对应工具链并确认在 PATH 中。
- Windows:安装
- ModuleNotFoundError(第三方依赖)
- 记住模块模式不会打包外部依赖,需在目标环境
pip install这些依赖。
- 记住模块模式不会打包外部依赖,需在目标环境
- 包结构问题
- 子目录缺少
__init__.py会导致子包未被包含。补齐后重编译。
- 子目录缺少
- .pyi 没被 IDE 识别
- 确认
.pyi与.pyd位于同一层级,.pyi位于yourpkg/目录中,且目录内不要放__init__.py(.py文件),否则会遮蔽.pyd。
- 确认
- 大小与编译时间
- 只包含需要的包:
--include-package=yourpkg足够。谨慎添加过多include选项以免体积膨胀。
- 只包含需要的包:
八、从零到一的完整示例
- 安装依赖
python -m pip install -U nuitka mypy
- 编译包为 .pyd
python -m nuitka --module yourpkg --include-package=yourpkg --output-dir=nuitka_build
- 生成 .pyi(递归)
python -m mypy.stubgen -p yourpkg -o nuitka_build
- 验证
- 在干净环境测试:
PYTHONPATH=./nuitka_build python -c "import yourpkg, yourpkg.submod; print('OK')" - 在 IDE 中把
nuitka_build加到解释器路径,检查自动补全是否生效。
- 在干净环境测试:
到这里,就拥有了一个“单文件 .pyd + 桩包 .pyi”的可分发形态:运行时只需 .pyd(和运行所需的第三方依赖),开发体验上 IDE 通过 .pyi 获得与源码同等的补全、跳转与类型提示。

浙公网安备 33010602011771号