如何通过pyproject.toml实现Python包可选子包的按需安装?
实现Python包foobar的按需模块安装配置
项目结构确认
先确保你的项目目录结构如下:
foobar/ ├── __init__.py ├── core/ │ ├── __init__.py │ └── 核心业务代码文件 ├── network/ │ ├── __init__.py │ └── 网络相关代码文件 └── plotting/ ├── __init__.py └── 绘图相关代码文件
pyproject.toml 完整配置
核心是通过可选依赖组+模块关联配置实现按需安装,以下是完整的配置示例:
[build-system] requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" [project] name = "foobar" version = "0.1.0" # 核心依赖:pip install foobar时默认安装 dependencies = [ "requests>=2.25.0", # 示例核心依赖,替换成你的实际依赖 ] # 默认仅安装core模块 packages = [ { include = "foobar" }, { include = "foobar.core" }, ] # 定义可选依赖组 [project.optional-dependencies] # 安装plotting模块及依赖:pip install foobar[plotting] plotting = [ "matplotlib>=3.4.0", # 示例绘图依赖,替换成你的实际依赖 ] # 安装network模块及依赖:pip install foobar[network] network = [ "aiohttp>=3.8.0", # 示例网络依赖,替换成你的实际依赖 ] # 安装全部模块及所有依赖:pip install foobar[all] all = [ "foobar[plotting,network]", ] # 关联可选依赖组与对应模块 [tool.setuptools.extras] plotting = ["foobar.plotting"] network = ["foobar.network"]
关键配置说明
- 默认安装控制:通过
[project.packages]指定仅包含foobar和foobar.core,确保pip install foobar只安装核心模块。 - 可选依赖组:
[project.optional-dependencies]定义不同场景的依赖集合,all组通过嵌套引用包含其他所有可选组。 - 模块与依赖组绑定:
[tool.setuptools.extras]将子模块(foobar.plotting、foobar.network)与对应的依赖组关联,用户安装对应extras时,会自动安装关联的模块。
代码兼容处理
为了避免用户未安装可选模块时导入报错,建议在foobar/__init__.py中使用延迟导入:
# 核心模块直接导入 from .core import * # 可选模块提供延迟导入入口 def load_plotting(): try: from . import plotting return plotting except ImportError: raise RuntimeError("plotting模块未安装,请执行 pip install foobar[plotting]") def load_network(): try: from . import network return network except ImportError: raise RuntimeError("network模块未安装,请执行 pip install foobar[network]")
测试验证
- 核心安装:运行
pip install ./foobar,检查site-packages目录下仅存在foobar/和foobar/core/。 - 绘图模块安装:运行
pip install ./foobar[plotting],检查site-packages新增foobar/plotting/及对应的依赖包。 - 全量安装:运行
pip install ./foobar[all],检查所有模块和依赖均已安装。
内容的提问来源于stack exchange,提问作者Campbell McDiarmid
相关产品推荐
相关产品推荐

