You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含多子项目的Python项目依赖管理最佳实践(无需Poetry/Conda)

多子项目pyproject.toml依赖管理与打包最佳实践(无Poetry/Conda)

方案1:用setuptools直接关联子项目依赖

这是最贴合标准打包流程的方案,父项目通过本地路径引用子项目,自动继承子项目的所有依赖,不用手动复制。

  • 先把每个子项目的pyproject.toml配置成可独立安装的包,比如子项目subproj_a的配置:
    [build-system]
    requires = ["setuptools>=61.0"]
    build-backend = "setuptools.build_meta"
    
    [project]
    name = "subproj-a"
    version = "0.1.0"
    dependencies = ["requests>=2.28.0"]
    
  • 父项目的pyproject.toml里,把每个子项目作为本地依赖引入:
    [build-system]
    requires = ["setuptools>=61.0"]
    build-backend = "setuptools.build_meta"
    
    [project]
    name = "parent-proj"
    version = "0.1.0"
    dependencies = [
        "subproj-a @ file://./subproj_a",
        "subproj-b @ file://./subproj_b",
        # 其他子项目按这个格式添加
    ]
    
  • 执行pip install .在父项目根目录,会自动安装所有子项目及它们的依赖;要生成本地wheel,直接运行python -m build就行,父项目的wheel会包含所有子项目的依赖声明,后续上传私有仓库也没问题。

方案2:写轻量Python脚本自动同步依赖

如果不想在父项目里硬编码子项目路径,写个小脚本遍历子项目,自动把所有子项目的依赖同步到父项目的pyproject.toml里,适配打包需求。

示例脚本:

import tomllib
import tomli_w
import os

# 改成你实际的子项目目录列表
SUBPROJECTS = ["subproj_a", "subproj_b", "subproj_c"]
PARENT_PYPROJECT = "pyproject.toml"

def get_subproject_deps(subproj_dir):
    pyproject_path = os.path.join(subproj_dir, "pyproject.toml")
    if not os.path.exists(pyproject_path):
        return []
    with open(pyproject_path, "rb") as f:
        data = tomllib.load(f)
    return data.get("project", {}).get("dependencies", [])

def update_parent_pyproject():
    # 读取父项目配置
    with open(PARENT_PYPROJECT, "rb") as f:
        parent_data = tomllib.load(f)
    
    # 收集所有子项目依赖并去重
    all_deps = set()
    for subproj in SUBPROJECTS:
        deps = get_subproject_deps(subproj)
        all_deps.update(deps)
    
    # 更新父项目的依赖列表
    parent_data["project"]["dependencies"] = list(all_deps)
    
    # 写回父项目的pyproject.toml
    with open(PARENT_PYPROJECT, "wb") as f:
        tomli_w.dump(parent_data, f)

if __name__ == "__main__":
    update_parent_pyproject()
    print("父项目依赖已同步完成")
  • 子项目依赖变更时跑一遍这个脚本,就能自动更新父项目的依赖。之后执行python -m build生成的wheel,会包含所有子项目的依赖,直接上传私有仓库或者本地使用都可以。

方案3:用requirements文件统一管理依赖

如果习惯用requirements文件,也可以写个脚本提取所有子项目的依赖,生成统一的requirements.txt,再让父项目引用这个文件打包。

示例bash脚本(需要先装yq工具:pip install yq):

#!/bin/bash

# 清空现有requirements.txt
> requirements.txt

# 遍历子项目提取依赖
for subproj in subproj_a subproj_b subproj_c; do
    if [ -f "$subproj/pyproject.toml" ]; then
        tomlq -r '.project.dependencies[]' "$subproj/pyproject.toml" >> requirements.txt
    fi
done

# 去重
sort -u requirements.txt -o requirements.txt

# 可选:直接安装依赖
# pip install -r requirements.txt
  • 然后在父项目的pyproject.toml里配置动态读取这个文件的依赖:
    [project]
    name = "parent-proj"
    version = "0.1.0"
    dynamic = ["dependencies"]
    
    [tool.setuptools.dynamic]
    dependencies = { file = ["requirements.txt"] }
    
  • 这样打包父项目时,setuptools会自动把requirements.txt里的依赖纳入wheel的声明中。

打包到本地或私有仓库的补充

不管用哪种方案,打包流程都很统一:

  1. 每个子项目单独生成wheel:进入子项目目录执行python -m build,生成的wheel可以存本地或者上传私有仓库。
  2. 父项目打包时,如果子项目是本地路径引用,生成的wheel会包含子项目的依赖声明;如果子项目已经上传私有仓库,父项目直接写子项目的包名和版本就行,比如"subproj-a>=0.1.0"。
  3. 上传私有仓库用twine upload --repository-url <你的私有仓库地址> dist/*,提前配置好仓库的认证信息即可。

内容的提问来源于stack exchange,提问作者Valeria

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 10:24:51