
pyproject.toml 本身不支持运行时环境变量插值,但可通过标准可选依赖机制 + 安装时显式声明(如 pip install mypkg[with-cdeps])实现等效逻辑,兼顾可重现性与构建灵活性。
pyproject.toml 本身不支持运行时环境变量插值,但可通过标准可选依赖机制 + 安装时显式声明(如 pip install mypkg[with-cdeps])实现等效逻辑,兼顾可重现性与构建灵活性。
在现代 Python 包管理中,pyproject.toml 是声明式配置文件,其内容在构建和分发阶段被静态解析,不支持执行 Python 代码或读取环境变量(如 os.environ)。因此,无法像旧式 setup.py 那样直接嵌入条件逻辑(例如 if os.environ.get("DO_NOT_INSTALL_THIS_PACKAGE"))。但这并不意味着丧失灵活性——正确做法是遵循 PEP 621 和 PyPA 最佳实践,将条件依赖建模为语义清晰的可选依赖组(optional dependencies)。
✅ 推荐方案:使用 project.optional-dependencies
在 pyproject.toml 中定义一个明确用途的可选依赖组(例如 cdeps),将 this_package 归入其中:
[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "mypkg" version = "0.1.0" dependencies = [ "requests>=2.28", "numpy>=1.23", ] [project.optional-dependencies] cdeps = ["this_package>=1.0.0"]
? 注意:cdeps 是自定义名称,可按需改为 with-clibs、native-build 等更具描述性的标识。
安装时,根据本地环境状态选择是否启用该依赖:
- 若系统已预装 C 库(且 this_package 的 wheel 不可用或无需编译),则仅安装基础包:
pip install mypkg
- 若需由 this_package 提供 C 库支持(例如在 CI 或无系统库的环境中),则显式启用可选依赖:
pip install mypkg[cdeps]
该方式完全兼容 pip、uv、poetry(需额外配置)及所有 PEP 517 构建后端,且生成的 .dist-info 元数据清晰可审计。
⚠️ 重要注意事项
- 不可在 pyproject.toml 中写 dependencies = [...] if os.getenv(...) else [...] —— 这会导致解析失败或未定义行为。
- 避免“反向命名陷阱”:不要命名为 no-cdeps;应正向命名(如 cdeps),默认不启用,符合用户直觉和工具链预期。
- 若需更细粒度控制(如跳过某依赖的编译步骤),可在 setup.cfg 或 pyproject.toml 的 [build-system] 下配合构建后端(如 setuptools 的 config_settings)实现,但属于进阶场景,通常不必要。
- 对于开发流程,可结合 pip install -e ".[cdeps]" 实现可复现的 editable 安装。
总之,用可选依赖替代运行时环境变量判断,不是妥协,而是拥抱标准化、可验证、跨工具链一致的现代打包范式。











