我不是突然开始讨厌 Python。我只是越来越不想继续维护那套大家默认接受了很多年的组合:pyenv + virtualenv + pip + pip-tools/poetry + 一点点 shell 脚本 + 一点点 CI 魔法。
这套东西不是不能用,而是它在 2026 年已经越来越像“历史兼容产物”,不是我愿意主动选的新起点。我的判断也很直接:如果你今天还要新开一个 Python 项目,尤其是个人项目、小团队服务、自动化脚本仓库,我会优先从 uv 开始,而不是先把老工具链重新拼一遍。
我为什么会重新审视这件事
过去很多人迁不动,不是因为老工具链好,而是因为没有一个足够完整的新选择。uv 早期更像一个超快的 pip 替代品,但现在它已经不是单点工具了。它开始覆盖项目管理、锁文件、workspace、Python 版本管理、tool 安装、构建后端,甚至连 Docker、Lambda 这类集成文档都已经补得越来越完整。
这件事真正重要的地方不在于“快了多少倍”,而在于你终于可以少维护几层状态:Python 版本是一套、虚拟环境是一套、依赖锁定是一套、命令执行又是一套。工具一多,表面上是模块化,实际上是责任分散。出了问题,你经常不知道该怪谁。
老组合真正烦人的不是安装,而是状态分裂
很多介绍会把问题说成“安装复杂”。我觉得这还不是最难受的。真正折磨人的是状态分裂。比如下面这种仓库,很多人都见过:
.python-version
pyproject.toml
poetry.lock
requirements.txt
requirements-dev.txt
Makefile
Dockerfile
.github/workflows/ci.yml
理论上每个文件都有自己的职责,实际上它们经常在表达同一件事:我要用哪个 Python,安装哪些包,测试时跑什么命令,发布时用哪套环境。文件一多,不一致就是迟早的事。
最典型的问题有几个:
- 本地用 pyenv 切到了 3.12,CI 还在 3.11;
- poetry.lock 更新了,但 Dockerfile 还在
pip install -r requirements.txt; - 开发同学用
poetry run pytest,脚本里写的是source .venv/bin/activate && pytest; - 临时脚本用系统 Python 跑过一次,依赖污染后半天找不到原因。
这些问题每个都不高级,但组合起来很耗人。个人开发者最怕的其实不是技术难题,而是这种“每次都不致命,但一直消耗注意力”的工程摩擦。
uv 真正值钱的地方,是把这些状态尽量收回一个入口
我现在更喜欢的起手方式会简单很多:
uv init demo-app
cd demo-app
uv python install 3.12
uv add fastapi uvicorn ruff pytest
uv sync
uv run pytest
这里面最关键的不是命令短,而是入口统一。项目、解释器、依赖、锁定、运行,至少不再分散在四五个工具之间。你看到 uv run 的时候,基本就知道它会在项目语境里执行;看到 uv sync,你知道它会对当前项目依赖和环境做收敛。
如果是 monorepo 或多包仓库,workspace 这件事也终于没那么别扭了。以前很多团队会在“继续拆 requirements”还是“切 Poetry workspace”之间犹豫很久,现在至少有了一个更统一的选项。
我真正喜欢的,是它开始影响 Docker 和 CI 的写法
工具好不好,不能只看本地体验。能不能进 CI、能不能进容器,才决定它是不是基础设施候选。uv 在这点上已经开始有工程意义了。
一个很实用的 Docker 片段大概会像这样:
FROM python:3.12-slim
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app
COPY pyproject.toml uv.lock ./
RUN --mount=type=cache,target=/root/.cache/uv
UV_LINK_MODE=copy uv sync --frozen --no-dev
COPY . .
CMD ["uv", "run", "python", "-m", "app"]
这里最让我在意的不是“语法新鲜”,而是它把缓存、锁文件、环境收敛放到了一条更直的路径上。以前很多镜像优化文章本质上都在教你怎么补旧工具链的洞,现在这条路径终于开始更像“默认工作流”。
但我不会把 uv 吹成银弹
我现在会优先推荐 uv,但不代表它已经没有迁移成本。至少有几件事要先想清楚:
- 老项目里如果已经深度绑定 Poetry plugin、私有源配置、定制发布流程,迁移不会是“半小时完成”;
- 团队成员对
pip和poetry很熟,不代表他们能立刻理解 uv 的项目模型和锁文件约定; - CI 如果混着系统 Python、预装缓存、历史脚本,第一轮清理经常比你想象的久;
- 部分第三方教程、脚手架、README 仍然默认围绕
pip install -r requirements.txt展开。
还有一个经常被忽略的问题:越是统一工具,越要控制版本漂移。因为它一旦覆盖了解释器、依赖和运行入口,出问题时影响面也会更集中。所以我会建议团队至少把 uv 版本固定在 CI 里,不要全员长期飘在 latest。
个人开发者现在最值得做的,不是全面迁移,而是先验证这三步
- 拿一个新项目,从
uv init到uv run pytest走完一遍; - 把 Dockerfile 里最旧的一段
pip install改成基于锁文件的uv sync --frozen; - 把一个常用 CLI 工具改成
uv tool install或uvx方式运行,观察本地状态是不是更干净。
这三步做完,你基本就能判断它是不是适合你的工作流,而不是停留在“我知道它很快”这种信息层面。
我的判断
uv 现在已经不是“Python 生态里一个很酷的新工具”了,它正在变成新的默认起点候选。对个人开发者和小团队来说,它最有价值的地方不是性能数字,而是能少维护几层状态、少记几套命令、少在 CI 和容器里打补丁。
我不会说所有 Python 项目都该立刻迁过去,但如果你今天还在新项目里继续复制那套 pip + pyenv + poetry + 手写脚本 组合,我觉得你至少应该认真问一句:这到底是成熟,还是只是习惯。