MENU

从 requirements.txt 到 pyproject.toml:现代 Python 项目升级实战指南(含依赖分析与 Docker)

October 29, 2025 • 浏览量: 15 • 字数: 4148 • 阅读时长: 2分钟 • 后端

AI摘要

用 pipdeptree 清理顶级依赖,再用 uv 迁移至 pyproject.toml 并锁定版本,实现可复现、可部署的现代 Python 依赖管理。

🧱 一、现实问题:requirements.txt 的“依赖泥潭”

在老项目中,常见的现象是这样的:

$ pip list
Package         Version
--------------- --------
numpy           1.24.3
pandas          2.0.1
requests        2.31.0
urllib3         2.0.4
charset-normalizer 3.2.0
idna            3.4
fastapi         0.95.2
uvicorn         0.22.0
pydantic        1.10.11
...

看起来一切正常,其实乱得很。
因为 requirements.txt 里可能只有 3~5 个包:

fastapi==0.95.2
pandas==2.0.1
uvicorn==0.22.0

pip list 却列出了几十个依赖。这时有两个关键问题:

  1. 哪些是项目自己需要的?
  2. 哪些是​依赖的依赖(transitive dependencies)

我们要在迁移前先把这些关系理清,否则迁移到 pyproject.toml 之后仍旧是混乱的。

🧩 二、精准识别“主依赖” vs “传递依赖”

1️⃣ 使用 pipdeptree 分析依赖树

安装:

pip install pipdeptree

查看依赖层级:

pipdeptree --warn silence

示例输出:

fastapi==0.95.2
  - pydantic [required: <2.0.0, installed: 1.10.11]
  - starlette [required: <1.0.0, installed: 0.27.0]
pandas==2.0.1
  - numpy [required: >=1.20.3, installed: 1.24.3]
  - python-dateutil [installed: 2.8.2]
  - pytz [installed: 2023.3]
uvicorn==0.22.0
  - click [installed: 8.1.3]
  - h11 [installed: 0.14.0]

👉 很明显,fastapipandasuvicorn 是你主动安装的;
其余如 pydanticnumpystarlette 等都是“传递依赖”。

Tip: 你可以用 pipdeptree --reverse 反查:哪个包依赖了这个库。

🧮 三、清理并锁定顶级依赖

1️⃣ 提取顶级包

pip freeze > all.txt
pipdeptree --warn silence --freeze > tree.txt

打开 tree.txt,手动(或脚本)过滤掉那些被其他包引用的依赖。

最终保留的核心依赖(即​顶级包​)写入新的 requirements.txt

fastapi==0.95.2
pandas==2.0.1
uvicorn==0.22.0

2️⃣ 验证清理是否正确

先创建个全新虚拟环境:

python -m venv cleanenv
source cleanenv/bin/activate
pip install -r requirements.txt
pipdeptree

如果依赖树和原项目行为一致,你的“核心依赖集”就整理对了。

🧭 四、迁移到 pyproject.toml + uv

安装 uv(强烈推荐):

curl -LsSf https://astral.sh/uv/install.sh | sh

初始化:

uv init

导入依赖:

uv add --from-requirements requirements.txt

查看结果(生成的 pyproject.toml):

[project]
name = "movie-analyzer"
version = "0.1.0"
dependencies = [
    "fastapi==0.95.2",
    "pandas==2.0.1",
    "uvicorn==0.22.0",
]
requires-python = ">=3.10"

🧰 五、验证和同步依赖

锁定依赖版本:

uv lock

安装依赖:

uv sync

验证运行:

uv run python main.py
uv 会自动生成 .venvuv.lock,确保依赖一致性。
即使协作者在另一台机器,也能完美复现同样的环境。

🧱 六、用 Docker 打包部署

这是最通用、最干净的构建方式。

FROM python:3.11-slim AS base

# 安装 uv
RUN pip install uv

WORKDIR /app

# 拷贝依赖文件
COPY pyproject.toml uv.lock ./

# 安装依赖
RUN uv sync --frozen --no-cache

# 拷贝源码
COPY src ./src

# 入口命令
CMD ["uv", "run", "fastapi", "run", "--host", "0.0.0.0", "--port", "8000"]

构建镜像:

docker build -t docker-test .

运行容器:

docker run -p 8000:8000 docker-test

🔍 七、附:自动识别“顶级依赖”的脚本

如果你懒得手动筛选,可以用这个 Python 脚本快速过滤:

import subprocess

def get_top_level_packages():
    output = subprocess.check_output(["pipdeptree", "--warn", "silence"]).decode()
    top_level = []
    for line in output.splitlines():
        if not line.startswith(" "):  # 顶级包
            pkg = line.split("==")[0]
            top_level.append(pkg)
    return top_level

if __name__ == "__main__":
    for pkg in get_top_level_packages():
        print(pkg)

执行:

python find_top_deps.py > clean_requirements.txt

它会自动生成仅包含“主依赖”的 requirements.txt。

⚡ 八、实战总结

步骤工具作用
依赖分析pipdeptree查出依赖关系树
顶级提取脚本 or 手动确定哪些是核心依赖
环境验证venv+pip install确认依赖可重现
现代化迁移uv init + add生成 pyproject.toml
锁定同步uv lock + sync可重复依赖管理
部署打包Docker + uv一致性环境交付

🧠 九、总结

“requirements.txt 是笔记本,而 pyproject.toml 是配置中心。”

通过 pipdeptree 清理依赖、再用 uv 统一管理,
你能把老项目彻底从“依赖泥潭”里拔出来,
同时获得更快的安装、更好的团队协作与更稳定的部署。

Archives QR Code Tip
QR Code for this page
Tipping QR Code