Skip to main content

用 uv 管理 Python 项目:从 requirements.txt 到可复现环境

October 17, 2026
介绍已有 requirements.txt 的 Python 项目迁往 uv 的两条路线,区分依赖声明、uv.lock 与解释器选择,说明 locked 和 frozen 的差异,并覆盖 CI 重建、验收和回退。
用 uv 管理 Python 项目:从 requirements.txt 到可复现环境

更新日期:2026-10-18

一个 Python 项目在开发机上正常运行,换到 CI 或服务器却报错,常见原因是 Python 版本、依赖范围和实际安装结果没有一起管理。uv 可以帮助整理这些环节,但迁移时仍要分清依赖声明、锁文件与运行环境。

本文面向已有 requirements.txt 的普通 Python 应用,采用独立工作副本演练。命令依据 Astral 官方项目指南与同步文档核对,不要求替换系统 Python,也不建议把旧虚拟环境复制到生产机器。

三类文件各自负责什么

文件作用不能替代什么
pyproject.toml项目元数据、Python 范围、直接依赖等不等于完整解析结果
uv.lockuv 解析出的依赖锁定信息不保证所有平台都能运行应用
.python-version当前目录选择的 Python 版本不替代 requires-python 兼容范围

一个项目可以声明支持若干 Python 版本,同时让本地开发固定使用其中一个版本。前者是兼容范围,后者是实际解释器选择。CI 还应记录 uv 版本、操作系统与架构。

迁移前先冻结现状

在现有项目中保存工作状态,记录原解释器、依赖与测试结果。如果 requirements.txt 是从一个长期使用的环境导出的,里面可能包含间接依赖和与项目无关的工具,不能直接视为精心维护的直接依赖列表。

python --version
python -m pip --version
python -m pip freeze
git status --short

命令需在原项目环境内执行。输出可能含私有依赖地址,归档时检查凭据。pip freeze 记录安装状态,不负责计算新的依赖锁定方案,这一点在官方说明中有明确区分。

路线一:先保留 requirements 工作流

如果暂时不想改项目结构,可以先用 uv 的 pip 接口建立新虚拟环境。这里选择 Python 3.12 仅用于示例,实际应使用项目已经验证的版本。

uv --version
uv venv --python 3.12
uv pip sync requirements.txt
uv pip check

在全新副本中执行,避免覆盖正在使用的 .venv。sync 会使环境与输入清单对齐;若输入只列直接依赖、并未包含完整依赖集合,应该先准备经过解析的完整清单,或选择合适的安装流程,不能假定它等价于任意 pip install -r 场景。

这种方式适合先验证工具与现有部署的配合,但它没有自动把项目转换为基于 pyproject.toml 和 uv.lock 的管理方式。

路线二:迁移到 uv 项目管理

在已有代码但还没有 pyproject.toml 的工作副本中,执行:

uv init --bare --python 3.12
uv python pin 3.12
uv add -r requirements.txt
uv sync --locked

--bare 建立最小项目配置,--python 3.12 避免初始化时根据本机较新的解释器生成不匹配的最低版本要求。随后固定解释器并导入依赖,会生成或更新锁定结果。若项目已经有 pyproject.toml,不要重新初始化,先检查原有构建后端、requires-python、依赖和工具配置,再决定如何整合。uv 项目指南

导入之后必须查看文件差异。特别留意被导出的间接依赖是否全部变成直接约束、平台专用包是否需要标记,以及 requirements 文件里的索引或本地路径是否能在其他机器上使用。

对已有约束文件,可以按官方支持的方式与导入配合;不要悄悄移除约束来“解决冲突”,因为它们可能来自真实兼容问题。

locked 与 frozen 不应混用

uv sync --locked 要求锁文件与项目声明保持一致,否则失败;--frozen 跳过锁文件是否需要更新的检查,按现有锁文件操作。CI 希望发现“改了声明却没更新锁文件”时,通常应使用前者。同步与锁定文档

不要为了让构建变绿,直接把 --locked 换成 --frozen。先确认声明和锁文件为何不同,修复后提交两者。

建议至少提交 pyproject.toml、uv.lock,以及项目采用的 Python 版本选择文件;虚拟环境本身不提交。部署机器根据这些文件重建环境,才能避免开发机中的绝对路径与原生扩展残留。

把测试和开发工具放到对应依赖组

例如项目使用 pytest,可以在确认需要后添加为开发依赖:

uv add --dev pytest
uv run --locked pytest

这条测试命令以项目已经有 pytest 测试为前提,没有测试文件时不会自动获得验证证据。实际应用还要执行构建、导入、启动与核心业务验收。

发布环境可根据项目结构选择不安装开发依赖,但运行所需的工具必须正确声明,不能碰巧依赖开发环境里存在的包。例如迁移命令若是发布步骤的一部分,就应明确它在哪个阶段、哪个环境运行。

CI 和部署需要固定的不止依赖

一份可复现记录还应包含 Python 版本、uv 版本、基础镜像或操作系统、CPU 架构,以及私有索引配置。涉及原生扩展时,编译器和系统库也会影响构建。

CI 的基本顺序是安装约定版本的工具、同步锁定依赖、运行测试、构建制品。秘密通过 CI 的凭据机制注入,不写进 pyproject.toml 或锁文件里的 URL。

上线前在与生产接近的环境重建一次,而不是重复使用开发机缓存。缓存可以提高速度,但不应该成为让构建成功的隐藏依赖。

出问题时如何退回

迁移初期保留原 requirements 文件、旧部署配置与上一版制品。若 uv 迁移出现问题,可以退回旧代码和部署方式,在新的虚拟环境按原流程安装;不要在已经同步过的环境里不断交替运行不同工具来猜测状态。

对数据库或业务状态的更改,应采用应用自己的兼容与回退方案。依赖环境回退不自动撤销数据库迁移。

验收至少包括:清洁环境重建成功、锁文件检查通过、测试通过、应用能够启动、主要业务动作完成。项目真正可维护的标志,是另一台机器根据记录能够重建,而不是本机安装速度变快了。

官方资料与继续阅读