📖 知识点简介
项目写大了,依赖管理就成了刚需。今天带你绕开 Python 依赖管理的经典雷区:搞清楚 requirements.txt 的江湖地位、体验 uv 这个下一代包管理器的闪电速度、搞懂私有源怎么配、离线包怎么装、以及终极方案 pyproject.toml 的统一标准。
1️⃣ requirements.txt --- 最朴素的依赖锁
基础用法
txt
# requirements.txt
requests>=2.28.0
flask==2.3.3
numpy~=1.25.0 # 兼容 >=1.25.0, <1.26.0
pandas<2.0.0
bash
# 安装
pip install -r requirements.txt
# 导出当前环境的依赖
pip freeze > requirements.txt
# 只导出顶层依赖(推荐,pip 无原生支持,用 pip-tools)
pip install pip-tools
pip-compile requirements.in # 自动生成 requirements.txt(含所有传递依赖)
🚨 避坑:pip freeze 三大陷阱
| 陷阱 | 问题 | 正确做法 |
|----------|------------------------|----------------------------------------|------------------------------------|
| 全量导出 | 连 pip、setuptools 都写进去了 | 用 `pip freeze | grep -v "^pip|^setuptools"` 过滤 |
| 无顶层/传递区分 | 100 行依赖,不知道哪些是直接装的 | 用 pip-compile 或直接写 requirements.in |
| 无哈希校验 | 坏人篡改包版本,pip 不检查 | 用 pip freeze --hash 生成带哈希版本 |
生产级的分组方案
csharp
requirements/
├── base.txt # 公共依赖
├── dev.txt # 开发时额外依赖
│ └── -r base.txt # 继承 base
├── test.txt # 测试依赖
│ └── -r base.txt
└── prod.txt # 生产依赖(锁定精确版本)
└── -r base.txt
txt
# requirements/dev.txt
-r base.txt
pytest>=7.0
black>=23.0
pdbpp>=2.0
2️⃣ pyproject.toml --- 现代 Python 的标准
PEP 621 把项目元数据统一到 pyproject.toml。不管用 pip、poetry、uv、pdm,共享同一份配置。
基本结构
toml
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "my-awesome-app"
version = "0.1.0"
description = "一个超棒的应用"
requires-python = ">=3.11"
dependencies = [
"requests>=2.28",
"flask>=2.3,<3.0",
"pydantic>=2.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7",
"black>=23",
"ipython",
]
test = [
"pytest-cov>=4",
"pytest-mock>=3",
]
安装依赖
bash
# pip 从 pyproject.toml 安装(pip 21.3+)
pip install -e . # 可编辑安装(开发模式)
pip install ".[dev]" # 安装 + dev 可选依赖
pip install ".[dev,test]" # 多组可选依赖
🚨 pyproject.toml vs setup.py
arduino
pyproject.toml setup.py
┌──────────────────────┐ ┌────────────────────────┐
│ 声明式(声明"要什么")│ │ 命令式(描述"怎么装") │
│ 可读性好、无副作用 │ │ 可以写 Python 代码 │
│ 标准统一、推荐方案 │ │ 历史遗留、逐渐淘汰 │
└──────────────────────┘ └────────────────────────┘
金科玉律 :新项目只写
pyproject.toml。除非你要写复杂的 C 扩展构建逻辑,才需要保留setup.py。
3️⃣ uv --- 下一代包管理器(⚡ 快 10-100 倍)
uv 是 Rust 写的 pip 替代品,兼容 pip 的 requirements.txt 和 pyproject.toml。
安装 uv
bash
# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# 或者用 brew(推荐)
brew install uv
常用命令
bash
# 创建虚拟环境(比 venv 快 50 倍)
uv venv .venv
# 安装依赖(自动创建 venv)
uv pip install requests flask
# 从 requirements.txt 安装
uv pip install -r requirements.txt
# 从 pyproject.toml 安装
uv pip install -e .
# 锁定精确版本(生成 uv.lock)
uv lock
# 根据 lock 文件同步环境
uv sync
# 导出为 requirements.txt
uv pip freeze > requirements.txt
# 升级所有包
uv pip sync requirements.txt
uv lock 的优势
bash
# 1. 生成 uv.lock(包含哈希校验和传递依赖)
uv lock
# 2. 别人拉代码后,一秒恢复一模一样的环境
uv sync
对比传统 pip + pip freeze:
| 场景 | pip | uv |
|---|---|---|
| 首次安装 100 个包 | ~30s | ~1s |
| lock 文件生成 | pip-tools 手动 | uv lock 一键 |
| 依赖解析 | 慢(纯 Python) | 快(Rust 并行) |
| 哈希校验 | 需手动 --hash | 默认全量校验 |
4️⃣ 私有源(Custom Index)
公司内部包或镜像源怎么配?用 --index-url 或 PIP_INDEX_URL 环境变量。
命令行方式
bash
# 临时替换为清华镜像
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# uv 版
uv pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple
配置文件方式(推荐)
ini
# ~/.pip/pip.conf 或项目根目录 pip.conf
[global]
index-url = https://pypi.tuna.tsinghua.edu.cn/simple
trusted-host = pypi.tuna.tsinghua.edu.cn
[install]
# 额外附加的私有源
extra-index-url =
https://my.company.com/pypi/simple/
私有源认证
bash
# 方式 1:URL 嵌入用户名密码
pip install my-internal-lib \
-i https://user:password@private.pypi.local/simple/
# 方式 2:keyring 集成(推荐,密码存系统钥匙串)
pip install keyring
# 首次会提示你输入,之后自动读取
🚨 避坑:私有源加 --trusted-host
如果没有 HTTPS 证书,需要手动信任:
bash
pip install my-pkg --trusted-host private.pypi.local
否则出现 Unverified HTTPS request 警告。
5️⃣ 离线包安装(在公司内网或无网络环境)
场景 A:有网机器下载,无网机器安装
下载阶段(有网机器):
bash
# 下载所有依赖到 offlin_pkgs/ 目录
pip download -r requirements.txt -d offline_pkgs/
# uv 版
uv pip download -r requirements.txt --target offline_pkgs/
安装阶段(无网机器):
bash
# 从本地目录安装,不联网
pip install --no-index --find-links=./offline_pkgs/ -r requirements.txt
场景 B:把整个 PyPI 镜像到本地
bash
# 使用 bandersnatch 同步完整镜像(不常用,适合企业)
pip install bandersnatch
场景 C:单文件 Wheel 安装
bash
# 你已经下载了 .whl 文件
pip install requests-2.31.0-py3-none-any.whl
⚡ 避坑 & 要点总结
| # | 要点 | 说明 |
|---|---|---|
| 1️⃣ | 永远用虚拟环境 | python -m venv .venv 是最低要求,别污染系统 Python |
| 2️⃣ | 生产环境锁定版本 | requirements-prod.txt 必须锁到 patch 版本号 |
| 3️⃣ | pip freeze 有坑 | 全量导出含无关包,用 pip-compile 或 uv lock |
| 4️⃣ | 新项目用 pyproject.toml | 别写 setup.py 了,除非有 C 扩展 |
| 5️⃣ | uv 是 pip 的超集 | 可以逐步迁移,命令几乎 1:1 对应 |
| 6️⃣ | 私有源配 extra-index-url | 同时保留公共源和私有源 |
| 7️⃣ | 离线包用 --no-index |
配合 --find-links 离线部署 |
python
# 调试小技巧:看看当前环境安装了哪些包、版本和位置
import pkg_resources
for pkg in sorted(pkg_resources.working_set, key=lambda x: x.key):
print(f"{pkg.key:25s} {pkg.version:15s} {pkg.location}")