使用 python -m build 打 wheel 前必须确保 pyproject.toml 合规:[build-system] 中 requires 至少含 "setuptools>=45" 和 "wheel",[project] 中 name 必须与源码目录严格一致,c/c++ 扩展需显式声明构建依赖且路径、模块名、导入语句须完全匹配。

用 python -m build 打 wheel 前必须确认 pyproject.toml 是否合规
没有 pyproject.toml,python -m build 会回退到旧式构建逻辑,甚至静默忽略 C 扩展;哪怕你写了 setup.py,它默认也不会被读取(除非加 --legacy)。
关键段落必须存在且写对:
-
[build-system]中requires至少含"setuptools>=45"和"wheel";若含 C++,还得加"scikit-build>=0.13"或"setuptools-rust"等对应后端 -
[project]里name必须与源码目录名/命名空间严格一致(比如name = "mylib"→ 源码得在src/mylib/或顶层mylib/) - 含 C/C++ 时,
[project.optional-dependencies]或[build-system]需显式声明构建依赖,如"cmake>=3.18"、"ninja"
src/ 目录结构不匹配会导致 C 模块导入失败
常见现象是 pip install xxx.whl 成功,但 import xxx 报 ModuleNotFoundError 或 ImportError: dynamic module does not define module export function —— 这往往不是编译问题,而是包路径没对上。
检查点:
- 如果
pyproject.toml中project.name = "fastmath",则 C 模块的 Python 封装(如__init__.py)必须位于src/fastmath/下,不能是fastmath/或src/fast_math/ - C 扩展的模块名(
Extension("fastmath.core", ...))要和from fastmath import core的导入路径一致 - 使用
scikit-build时,CMakeLists.txt中的add_library(_core MODULE ...)生成的文件名(如_core.cpython-311-x86_64-linux-gnu.so)必须能被__init__.py正确加载,通常靠importlib.util.spec_from_file_location或直接from . import _core
跨平台打包时 ABI 标签和编译工具链必须匹配
在 macOS 上用 Xcode 编译出的 .so,打出来的 wheel 文件名带 macosx_13_0_arm64,Windows 用户 pip install 会直接报错 “not a supported wheel on this platform”。这不是 bug,是 wheel 设计本意。
实操要点:
- Windows:必须安装 Visual Studio Build Tools(非仅 VS IDE),且版本需匹配目标 Python(如 Python 3.11 要用 MSVC 14.3+);命令行运行
vcvarsall.bat amd64再执行python -m build - Linux:CI 中常用
cibuildwheel+manylinux镜像;本地测试可装auditwheel,打包后跑auditwheel show dist/*.whl看是否含非法系统库依赖 - macOS:确保
MACOSX_DEPLOYMENT_TARGET环境变量设为最低支持版本(如11.0),否则生成的 wheel 可能在旧系统上加载失败
验证 wheel 是否真正“开箱即用”不能只看 pip install 是否成功
很多开发者打包完就上传 PyPI,结果用户反馈“安装成功但 import 失败”——因为 pip install 只校验元数据和文件完整性,不运行任何代码。
最小验证流程:
- 新建干净虚拟环境:
python -m venv .tmpvenv && .tmpvenv/bin/python -m pip install --no-deps dist/*.whl(Windows 用.tmpvenv\Scripts\python.exe) - 进该环境,执行
python -c "import mylib; mylib.test_basic()"(你得提供一个无副作用的测试函数) - 用
python -m wheel unpack dist/*.whl解包,检查mylib-*.dist-info/METADATA里Requires-Dist是否漏了numpy或pybind11这类运行时依赖(它们不是构建依赖)
最易被忽略的是:C 扩展的符号表未导出、PyInit_* 函数名拼错、或 __init__.py 里 import 语句路径错误——这些都不会在 build 阶段报错,只会在 import 时暴露。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











