sync 与 pip 工作流全对比

最近把团队的 Python 依赖管理从 pip 迁到了 uv,速度快得离谱,但有个问题一直有人问:

“uv sync 和 uv venv && source .venv/bin/activate && uv pip install -r requirements.txt 不都是装依赖吗?有啥区别?”

表面看都是“建环境 + 装包”,但底层是两套完全不同的工作流范式。一个走 uv 的项目管理(声明式)路线,一个走兼容 pip(命令式)路线。搞混了,就会遇到“在我机器上是好的”这类经典事故。

这篇文章把二者的差异一次讲清楚,并给出选型建议。

一、两条命令长什么样

命令 A —— uv 的项目工作流:

uv sync

命令 B —— uv 的 pip 兼容工作流:

uv venv
source .venv/bin/activate
uv pip install -r requirements.txt

就差这几个字,行为却天差地别。

二、一句话本质区别

uv sync 是声明式的:你声明“我需要什么”,uv 负责把环境对齐成那个样子,多退少补。
uv pip install 是命令式的:你下一条指令,它就执行一条,只管往上堆,不管环境现状。

三、五大核心差异

1. 依赖信息从哪读

  • uv sync:读取 pyproject.toml(声明依赖)+ uv.lock(锁定版本),优先按 lock 精确还原。
  • uv pip install -r:只读 requirements.txt,完全不认识 pyproject.toml。里面是范围约束还是精确版本,全看你自己的写法。

2. 可复现性

  • uv sync:因为有 uv.lock,团队和不同机器装出来的版本完全一致,这是它最大的卖点。
  • uv pip install -r:如果 requirements.txt 没锁死版本(比如写着 requests>=2.0),每次可能拉到不同的新版,环境悄悄漂移。

3. 环境状态管理

  • uv sync:把环境对齐成“恰好等于声明的依赖集合”,多出来的包(extraneous)会自动清理,环境始终干净。
  • uv pip install:累加式,只往里装,不会帮你删掉手抖多装的包。

4. 是否安装“你自己的项目”

  • uv sync:默认把当前项目本身以可编辑模式(editable)一起装进 .venv,本地开发直接 import 自己。
  • uv pip install -r:只装 requirements.txt 里的东西,不碰项目本身(除非你把 -e . 写进 requirements)。

5. 需不需要激活虚拟环境

  • uv sync:不需要 source 激活。uv 自动管理 .venv,直接 uv run python / uv run xxx 就能用对的环境。
  • uv pip install:需要先激活 venv(或显式 uv pip install --python .venv/bin/python),否则可能装到别的环境去。

四、对照表

维度uv syncuv venv && activate && uv pip install -r
依赖来源pyproject.toml + uv.lockrequirements.txt
可复现✅ 强(lock 锁版本)⚠️ 取决于 requirements 是否锁定
环境清理✅ 自动移除多余包❌ 只增不减
安装本项目✅ 默认 editable❌ 不装
需要激活❌ 不需要✅ 需要(或指定 --python)
典型定位项目开发 / 协作首选兼容旧 pip 习惯、复用已有 requirements

五、怎么选型

  • 新项目 / 要协作 / 要可复现 → 用 uv sync,配合 uv add 管理依赖,把 uv.lock 提交进版本库。
  • 只是想拿 uv 当“更快的 pip”、手头只有 requirements.txt → 用后者也行,但强烈建议用 uv pip compile 把 requirements.txt 锁成精确版本,避免漂移。

六、从 requirements.txt 迁移到 uv sync 的建议

如果你现在还是 requirements.txt 那一套,迁移成本很低:

# 1. 初始化 pyproject.toml(如果还没有)
uv init

# 2. 把 requirements 里的依赖加进项目
uv add -r requirements.txt

# 3. 之后统一用 sync 还原环境
uv sync

从此团队里每个人、每次 CI,装的都是一模一样的版本。

结语

uv sync 和 uv pip install 不是“新旧替换”的关系,而是两种心智模型:一个是“我要环境长成什么样”,一个是“我要装哪个包”。新手建议直接上 uv sync,把可复现性交给 lock 文件;老项目想渐进迁移,先用 uv pip compile 锁版本,再慢慢搬进 pyproject.toml。

用对了工作流,能省掉一半“在我机器上是好的”式扯皮。

评论

此博客中的热门博文

通过命令行在Github上发布项目的新版本

利用GitHub免费的静态页面托管空间发布网页

本地部署OpenAvatarChat实时交互数字人系统