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

如何从setup.py读取顶层依赖并将固定版本依赖写入install_requires?

使用pip-tools固定Python包依赖版本并同步至setup.py

核心思路

先维护无版本限制的顶层依赖列表,用pip-tools锁定所有依赖(直接+间接)的版本,再将顶层依赖的固定版本同步回setup.py的install_requires字段——既保证生产环境依赖稳定,又能方便跟踪和更新顶层依赖。

具体操作步骤

1. 调整setup.py结构,分离顶层依赖

把无版本限制的顶层依赖单独定义,方便后续维护和跟踪:

#!/usr/bin/env python
import pathlib
from setuptools import setup, find_packages

# 定义顶层依赖(无版本限制,作为依赖管理的基准)
TOP_LEVEL_DEPS = ["package1", "package2"]

setup(
    author="Foo",
    description="My package",
    install_requires=[],  # 后续将填充锁定后的版本
    extras_require={
        "top_level": TOP_LEVEL_DEPS,
    },
    version="0.1.0",
)

2. 用pip-compile生成锁定的依赖文件

基于setup.py里的top_level extras,生成包含所有依赖(直接+间接)固定版本的requirements.txt:

pip-compile --extra=top_level setup.py

运行后会生成类似这样的requirements.txt:

#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile --extra=top_level setup.py
#
package1==1.0.0
package2==2.1.0
dependency-of-package1==3.0.0  # via package1

3. 提取顶层依赖的固定版本,同步至setup.py

requirements.txt包含间接依赖,而install_requires只需要你的包直接依赖的顶层包版本,所以要筛选对应行:

  • 手动筛选:从requirements.txt中找到package1和package2的版本行,替换setup.py里的install_requires:
    install_requires=["package1==1.0.0", "package2==2.1.0"],
    
  • 自动化处理(推荐):写个小脚本自动完成筛选和替换,避免手动出错:
    import re
    from pathlib import Path
    
    # 要和setup.py里的TOP_LEVEL_DEPS保持一致
    TOP_LEVEL_DEPS = {"package1", "package2"}
    
    # 读取requirements.txt
    reqs_path = Path("requirements.txt")
    req_lines = [line.strip() for line in reqs_path.read_text().splitlines()]
    
    # 筛选顶层依赖的固定版本行
    locked_reqs = []
    for line in req_lines:
        if not line or line.startswith("#"):
            continue
        pkg_match = re.match(r"^([a-zA-Z0-9_-]+)", line)
        if pkg_match and pkg_match.group(1) in TOP_LEVEL_DEPS:
            locked_reqs.append(line)
    
    # 更新setup.py的install_requires字段
    setup_path = Path("setup.py")
    setup_content = setup_path.read_text()
    setup_content = re.sub(
        r"install_requires=\[.*?\],",
        f"install_requires={locked_reqs},",
        setup_content,
        flags=re.DOTALL
    )
    setup_path.write_text(setup_content)
    
    运行脚本后,setup.py的install_requires会自动更新为锁定的版本。

疑问解答

你问的「直接把requirements.txt内容读入install_requires」不可行——因为requirements.txt包含了你的包不需要直接声明的间接依赖,把这些写入install_requires会导致依赖冗余,甚至引发版本冲突。正确的做法是只提取顶层依赖的固定版本同步至install_requires。

注意事项

  • 每次更新顶层依赖(比如新增/移除包),都要重新运行pip-compile生成新的requirements.txt,再同步至setup.py。
  • 生产环境安装时,既可以用pip install .(基于setup.py的固定依赖),也可以用pip install -r requirements.txt(安装所有锁定的依赖,包括间接的)。
  • 要保证TOP_LEVEL_DEPS在setup.py和自动化脚本中完全一致,避免遗漏或错误匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 19:20:47