❝原文:https://emily.space/posts/251023-uv
作者:Dr. Emily L. Hunt
译者:Kurt Pan

现在是 2025 年。安装 Python、管理虚拟环境以及在同事之间同步依赖项真的就要那么难吗?其实不然!最近出现了一款名为 uv 的出色新工具,它彻底改变了 Python 的安装和使用方式。
uv 是一个免费的开源工具,由 Astral 开发。Astral 是一家小型创业公司,过去几年一直在开发 Python 工具(例如优秀的代码检查工具 Ruff )。uv 可以:
https://docs.astral.sh/ruff/
为你安装任意 Python 版本
安装软件包
管理虚拟环境
快速解决依赖冲突(这对大型项目至关重要 )。
最棒的是,在我看来,它在上述所有方面都比任何其他工具都做得更好。它的速度快得惊人 ,是用 Rust 编写的,几乎可以在任何操作系统或平台上运行。
uv 的安装非常简单 。有几种方法,但最简单的(在我看来)是使用这行单行命令——对于 Linux 和 Mac 系统,命令是:
curl -LsSf https://astral.sh/uv/install.sh | sh
或者在 Windows 系统下使用 PowerShell:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
然后你可以使用命令 uv 访问 uv。 安装 uv 不会影响你现有的任何 Python 安装 ——它是一个独立的工具,因此即使只是为了试用而安装也是安全的。
对于任何 Python 项目来说,使用虚拟环境始终是一个好主意。它可以将不同的代码片段和依赖项彼此隔离,而且根据我的经验,尽早养成使用虚拟环境的习惯可以省去很多麻烦。uv 本身就使用了虚拟环境,因此如果你开始使用 uv,就很容易上手使用它们。
uv 会根据你当前工作目录(或其父目录)中的 pyproject.toml 文件中的指定内容,为你构建一个 Python 环境。pyproject.toml 文件是一种标准的现代格式, 用于指定 Python 项目的依赖项。一个简单的 pyproject.toml 文件可能如下所示:
[project]
name = "my_project"
version = "1.0.0"
requires-python = ">=3.9,<3.13"
dependencies = [
"astropy>=5.0.0",
"pandas>=1.0.0,<2.0",
]
本质上,它只需要指定要使用的 Python 版本以及一些依赖项。 添加名称和版本号也是个不错的想法。
(附注:对于你以软件包形式发布的项目,例如发布到 pip 和 uv 使用的 Python 包索引的项目, pyproject.toml 文件是一种现代方式,可以指定发布软件包所需的一切信息 。)
要用uv创建一个新的 Python 项目,你可以运行
uv init
这将为你创建一个新项目,其中包含 pyproject.toml 、 README.md 和其他重要的样板代码。
运行此命令的方式有很多种,例如 uv init --bare (仅创建 pyproject.toml 文件)、 uv init --package (设置一个新的 Python 包)等等。建议运行 uv init --help 来了解详情。
pyproject.toml 文件项目初始化完成后(或者如果你的项目中已经存在 pyproject.toml 文件),使用 uv 就非常简单了。你只需要执行以下操作,在 pyproject.toml 文件所在的目录中:
uv sync
此命令(实际上,如果你尚未运行过,则大多数 uv 命令都会执行此操作)将:
.venv 目录中的新虚拟环境中uv.lock 文件,该文件保存每个已安装软件包的确切的、与平台无关的版本——这意味着其他同事可以完全复制你的 Python 环境。原则上,你可以像激活其他工具中常见的虚拟环境一样“激活”这个新的虚拟环境,但使用 uv 最“uv-onic”的方式是在任何命令前加上 uv run。这条命令会自动为你选择正确的虚拟环境,并在该环境中运行你的命令。例如,要运行一个脚本——不是
source .venv/bin/activate
python myscript.py
你可以这样做
uv run myscript.py
这将产生相同的效果。同样地,要使用像 Jupyter Lab 这样的“工具”,在你的项目目录中,你只需执行以下操作:
uv run jupyter lab
而不是先“激活”环境,然后再单独运行 jupyter lab 。
你当然可以手动编辑 pyproject.toml 文件:uv 会检测到更改并重建项目的虚拟环境。但 uv 也提供了更简便的添加依赖项的方法——你可以直接这样做。
uv add numpy>=2.0
添加软件包,包括指定版本限制(如上所示)。此命令会自动编辑你的 pyproject.toml 。uv add 也非常强大,可以从 Git 或计算机上的其他位置添加远程依赖项(但这里就不赘述了)。
最后,我认为 uv 最有用的功能之一是为你的项目指定一个特定的 Python 版本。
uv python pin 3.12.9
会将当前项目锁定在 Python 3.12.9 版本 ,适用于你和任何其他使用 uv 的用户——这意味着你真的可以在多台机器上复制完全相同的 Python 安装。
但有时,你可能只想快速运行一个工具——比如用 Ruff 检查代码,或者启动一个没有环境的 Jupyter notebook 服务器,甚至只是想快速启动一个安装了 pandas 的 IPython 会话来打开一个文件。uv tool 命令(别名 uvx )让这一切变得异常简单。运行如下命令:
uvx ruff
它会自动下载你想要使用的工具,并在一个一次性的虚拟环境中运行它。由于 uv 使用缓存,一旦工具下载完成,运行速度就会非常快。
有很多情况下我可能需要这样做——一个常见的例子是快速启动一个安装了 pandas 的 IPython 会话(使用 --with 添加依赖项),以便我可以快速打开并查看 parquet 文件。例如:
uvx --with pandas,pyarrow ipython
或者,也许只需要启动一个 Jupyter Lab 服务器,这样我就可以快速打开学生发给我的 Jupyter notebook:
uvx jupyter lab
或者说,还有很多其他奇奇怪怪、一次性的使用场景,在这些场景下, uvx 真的非常实用。 我并不觉得一直使用虚拟环境有什么损失 ,因为 uvx 总能在你需要的时候给你提供一张“免死金牌”。
我去年第一次接触到 uv,当时我正和我们其他几位优秀的开发者一起构建 Astrosky 生态系统 ——一个为在线天文爱好者构建开源社交媒体集成的出色项目。但是,由于多位开发者在不同的操作系统上异步工作,管理 Python 安装很快就成了一项艰巨的任务。
uv 对我们来说是一个极其强大的简化工具 ,我们在整个技术栈中都使用它。作为开发人员,我们都可以使用相同的 Python 安装,这一点尤为重要,因为我们使用的许多半实验性依赖项每次版本更新都会带来破坏性变更。在 GitHub Actions 上,我们计划使用 uv 快速构建 Python 环境并运行单元测试。在生产环境中,uv 已经管理了我们所有服务器上的 Python 环境。
最令人欣慰的是,我们始终确信 Python 和软件包的安装在所有机器上都能保持一致且正确 。 这就是为什么 uv 是近十年来 Python 生态系统最棒的创新。