UV 终极指南:速度提升 100 倍的 Python 包管理器
大多数 Python 开发人员都在处理环境和依赖项管理工具的碎片化问题。市面上有很多工具可供选择——pip、虚拟环境、Poetry 和 conda。所有这些工具都有各自的结构和要求。然而,当它们组合使用时,你很快就会发现它们会使任何必要的工作流程变得复杂。而这正是 UV 能够助你一臂之力的地方,它就是你所需要的真正的 Python 包管理器。
对于那些不了解的人来说,UV 是一个用Rust编写的现代高性能 Python 包管理器。无需理会其他工具,UV 的目标是将所有这些工具的功能整合到一个只需一个终端命令即可打开的条件式体验中。UV 由 Astral 开发,旨在与 pip、虚拟环境、pip-tools 以及 pyenv 的功能进行基准测试,最终目标是成为一个速度更快的一体化依赖项和环境管理工具!
什么是UV?
UV 是一个黑盒工具,它是一款用 Rust 编写的现代高性能 Python 包管理器和安装程序。它是 pip 等传统 Python 包管理器的直接替代品。它提供类似甚至更优的速度、更高的可靠性以及依赖项解析的一致性。UV 旨在解决 Python 生态系统中一些最明显的痛点。漫长的安装时间、依赖项解析的陷阱以及企业级环境管理的复杂性!所有这些痛点都是 UV 的典型用例,它拥有独特的架构和周到的实现,从而实现了快速和高效的包工作流程。它的速度比现有的包管理工具快 10 到 100 倍!
UV 的目标是通过提供以下集成功能来简化常见的 Python 开发工作流程:
安装包:类似于 pip。 管理环境:虚拟环境 的替代品。 锁定依赖项:提供 pip-tools 或 Poetry 的功能以实现可重复的构建。 管理 Python 版本:提供 pyenv 的替代方案。
与传统独立运行的工具不同,UV 为 Python 开发提供了一种统一的、“内置功能”的方法。它旨在减少开发人员需要管理的工具和命令的数量。
UV 突出的主要特点包括:
闪电般快速的包安装和依赖关系解析。 与现有的 Python 工具和工作流程兼容。 内置虚拟环境管理。 支持现代包装标准。 可靠的依赖锁定和可重现的环境。 内存高效的操作,尤其适用于大型项目。
无论是处理小型个人项目还是管理大型 Python 应用程序,UV 作为 Python 包管理器都提供了强大而高效的解决方案。
UV、Poetry、PIP + 虚拟环境 和 Conda:区别
开发人员在切换到新工具之前经常会问的第一个问题是“它与我正在使用的工具相比如何?”。在 Python 依赖项和项目管理领域,pip、Poetry、Conda 和 虚拟环境 已经是最常用的工具。然而,在当今可用的 Python 包管理器中,UV 也有其自身的优势。
UV 与 PIP 和虚拟环境
Pip 和 虚拟环境 一直以来都是用于Python 环境和包管理的独立工具。其中,pip 专门用于包管理,而 虚拟环境 专门用于隔离环境。下面简要介绍一下它们的优缺点:
– 大量的文档和社区支持 – 对于基础项目来说简单有效 | – 大型或复杂项目的依赖关系解析速度慢 – 没有内置的锁文件用于可重复性 |
UV 与 pip + 虚拟环境 相比的优势
从以下几个方面来看,UV 显然是两者中更可取的选择:
单一工具:UV 既可用于创建环境,也可用于安装软件包。只需一个命令 (uv) 即可同时完成这两项操作,从而简化了整体工作流程。 现代并行依赖解析器:UV 的解析器使用现代解析器,安装速度更快,因为它会在可能的情况下更快、更并行地安装依赖项。 锁文件创建(uv.lock):UV 自动为我们创建一个锁文件,这保证我们每次都安装相同的包版本,并提高了可重复性。
UV 与 pip + 虚拟环境 的示例
当使用 pip + 虚拟环境 设置环境并安装包时,这涉及:
virtualenv env
source env/bin/activate
pip install -r requirements.txt
使用 UV 时,你可以运行:
uv env create
uv install
UV 通常比 pip + 虚拟环境 更快地完成安装,并保证使用生成的锁文件在不同的机器上安装完全相同的软件包版本。
Conda 与 UV
Conda 是一个功能强大且功能多样的环境和包管理器,在科学界和数据科学领域被广泛使用。它旨在支持所有包(不仅仅是 Python 包),包括对执行更复杂的科学计算工作流程至关重要的系统级依赖项和系统库。
下面我们来看看 Conda 在 Python 开发方面的优势和劣势。
– 跨项目的强大环境隔离 – 跨 Windows、macOS 和 Linux 的一致行为 – 简化 Python 版本之间的切换 | – 消耗更多磁盘空间和内存 – 可能落后于 PyPI 的最新软件包版本 |
UV 相对于 Conda 的优势
以下是 UV 优于 Conda 的方面:
闪电般的软件包安装和环境设置:UV 采用 Rust 实现,优化了并行下载,并加快了软件包安装和环境创建的速度,从而显著提升环境速度。开发人员将受益于生产力的提升。 最少的内存和 CPU 使用率:UV 在执行操作时使用较少的内存和 CPU 资源,使其在非常受限的机器上或在每种资源使用都至关重要的 CI 管道内有效。 完全兼容 Python 打包标准:UV 基于与所有现有 Python 工具和格式(例如 requirements.txt 和 PyPI 索引)相同的打包标准构建。这使得开发人员无需迁移到新的生态系统或维护软件包列表即可使用 UV。 更容易集成到现有的 Python 工作流程:由于 UV 只关注 Python 包,因此它不会在系统级依赖管理方面引入太多额外的复杂性,并且可以与典型的 Python 开发环境无缝集成。
UV 与 Conda 的示例
使用 Conda 设置环境通常如下所示:
conda create -n myenv python=3.9 numpy scipy
conda activate myenv
而使用UV时,过程如下:
uv env create -p python=3.9
uv install numpy scipy
Conda 是科学和数据科学项目非常强大的工具,因为它能够管理系统级软件包,并在同一环境中提供多种平台支持。然而,使用 conda 在安装速度和内存占用方面存在一些缺点,这在某些情况下可能值得注意。
相比之下,UV 在主要考虑安装速度、低开销以及不脱离 Python 生态系统的情况下尤其有用。此外,当项目没有太多非 Python 依赖项时,使用 conda 仍然很有用且有利。
UV 与Poetry
Poetry 是一个现代化的一体化 Python 包管理器,它以有组织的、有主见的方式执行依赖管理、项目脚手架和包发布。
另请阅读:如何使用 Poetry 构建 RAG 评估器 Python 包?
– 内置项目脚手架可促进清晰的结构 – 集成发布到 PyPI 可简化部署 – poetry.lock生成可重复的构建 | – 大型项目的依赖关系解析速度较慢 – 与基于 pip 的混合工作流程存在兼容性问题 |
Poetry的优势
以下是Poetry的一些明显优势:
强大的依赖解析器:Poetry 可以处理依赖项之间的复杂版本冲突,并允许依赖项顺利地连接在一起。 内置项目结构:Poetry 提供项目脚手架并规定项目结构(布局),以便于保持一致的项目布局。 集成发布:Poetry 包含将包发布到 PyPI 的命令,使发布变得轻而易举。 可重复性:生成 poetry.lock 文件以跨机器创建可重复的环境。
Poetry的劣势
Poetry的一些局限性包括:
自以为是的工作流程:Poetry 提供的约定可能会降低想要以自己的方式配置项目的开发人员的灵活性。 依赖关系解析速度较慢:Poetry 的依赖关系解析器可能比 UV 的慢,这意味着在大型项目上安装依赖关系可能需要更长的时间。 兼容性问题:Poetry 的约定有时会以修改被认为是“正常”的基于 pip 的工作流程为代价,这有时会妨碍与其他工具组合的集成。
UV 相对于Poetry的优势
以下是 UV 作为 Python 包管理器胜过 Poetry 的一些原因:
极快的依赖关系解析:UV 通过其 Rust 实现利用快速计算来解析和安装依赖关系,从而在传统 Python 包管理器的一小部分时间内创建环境。 轻量高效:使用极少的系统资源即可快速构建环境。 与标准 Python 打包的兼容性:与强制开发人员按照其约定管理其 Python 环境和项目的 poetry 不同,UV 可以与现有的 requirements.txt 和 setup.py 很好地兼容,并且非常容易与 pip 和现有工具集成。 灵活的项目结构:与Poetry不同,UV 不规定任何特定的格式,允许开发人员一步一步地采用它,而无需改变他们做项目的方式。
例子
使用 Poetry 创建项目并添加依赖项:
poetry new myproject
cd myproject
poetry add requests flask
poetry install
Poetry 管理项目结构和环境。使用 UV,你可以在已构建的项目中安装依赖项:
uv install requests flask
UV 是关于快速安装和环境管理,无需“规定”结构布局,因此很容易逐步采用其缺乏结构的结构。
UV 入门:简单指南
所以,你决定尝试一下 UV 作为你的下一个 Python 包管理器。这是一个明智的选择,以下是具体操作方法。
步骤 1:安装 UV
你可以使用 curl 在 macOS 和 Linux 终端上安装 UV:
curl -LsSf https://astral.sh/uv/install.sh | sudo sh
在 Windows 上,从 PowerShell 运行它(必须以管理员权限运行):
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
你也可以使用 Homebrew 安装它:
brew install uv
支持 pip 安装,但不建议使用。安装完成后,请检查版本是否正常:
uv version
步骤 2:开始新项目
要使用 UV 启动新项目,你需要导航到已有的项目目录或创建新的项目目录:
mkdir myproject
cd myproject
uv init
例如,如果命令为 uv init explore-uv,它将创建一个名为 explore-uv 的新项目。第一个命令将创建一个项目目录 (explore-uv),并自动创建:
.gitignore .python-version README.md hello.py(示例文件) pyproject.toml(项目元数据和依赖项的主要配置文件)
步骤 3:向项目添加初始依赖项
UV 在一个命令中结合了创建环境和向项目添加依赖项:uv add
uv add scikit-learn xgboost
首次执行 uv add 时,UV 会在当前工作目录中创建一个新的虚拟环境,并安装你指定的依赖项。第二次运行 uv add 时,它将使用你现有的虚拟环境,并安装或更新你请求的新软件包。
UV 使用实时的现代依赖解析器来管理依赖项,它会分析整个依赖关系图并查找兼容的软件包版本,从而避免版本冲突。每次添加命令结束时,UV 都会使用你安装的版本更新你的 pyproject.toml 和 uv.lock 文件,从而维护准确的记录。
要删除依赖项及其子依赖项,请运行 uv remove:
uv remove scikit-learn
步骤 4:使用 UV 运行 Python 脚本
安装依赖项后,你可以使用 uv run 而不是使用 python script.py 来运行 Python 脚本:
uv run hello.py
此命令确保脚本在 UV 创建的项目虚拟环境中运行。
使用 UV 管理 Python 版本
以下是 UV 流线与 Python 版本协同工作的一些方法。
列出现有的 Python 版本
UV 可以检测你的机器上现有或已安装的 Python 版本:
uv python list --only-installed
此命令将显示 UV 找到的每个 Python 版本的列表,包括通过 Conda 或 Homebrew 安装的版本。
更改当前项目的 Python 版本
你可以随时为 UV 项目切换 Python 版本,只要新版本满足 pyproject.toml 文件中的 require-python 规范(例如,requires-python =“>=3.9”)。
设置 Python 版本:
uv python use 3.11
这会将 Python 版本嵌入到 .python-version 中并保持一致性。如果找不到请求的版本,UV 会下载并安装到 ~/.local/share/uv/python 中。然后,UV 会在项目目录中创建一个新的 venv 文件并替换旧的。更新 Python 版本后,你可能需要重新安装依赖项:
uv pip install -e .
如果遇到与“权限被拒绝”相关的错误,你可能需要使用 sudo (macOS/Linux) 或以管理员身份运行命令提示符 (Windows)。更好的选择是更改 UV 主目录的所有权:
sudo chown -R $USER ~/.local/share/uv # macOS or Linux
检查活动版本
uv python --version
了解 UV 工具
UV 工具还提供接口来管理将自己公开为命令行工具的 Python 包(black、flake8、pytest……)。
Black 是一种流行的 Python 代码格式化程序,可以自动重新格式化你的代码以遵循一致的风格,从而提高可读性并在整个项目中保持统一的代码风格。
uv tool run 指示 UV 运行一个工具,black 是工具名称(Python 代码格式化程序)。hello.py 是要格式化的目标文件。此命令会在你的 hello.py 文件上运行 Black,并根据 Black 的样式规则自动格式化该文件。
使用 uv 工具运行:
uv tool run black hello.py
使用更短的 uvx 命令:
uvx black hello.py
运行这些命令时,UV 会在其缓存中创建一个临时虚拟环境,安装该工具并从那里运行。这样,你无需在项目的虚拟环境中安装命令行工具即可使用它们,从而加快执行速度并简化项目依赖关系。清除 UV 的缓存后,这些缓存环境也会自动清理,非常适合偶尔使用开发工具。
UV 中的锁定文件是什么?
锁定文件 (uv.lock) 是 UV 中依赖管理的重要组成部分。每次运行 UV add 命令时,UV 都会创建和/或更新一个 uv.lock 文件。uv.lock 文件:
跟踪并记录所有依赖项及其子依赖项的确切版本。 通过“lock”环境之间的依赖版本来实现可重复的构建。 通过保持一致的软件包版本来帮助防止“dependency hell”。 允许安装更快,因为 UV 可以使用已经锁定的版本,而不必再次解决依赖关系。
UV 会自动跟踪锁定文件,你应该将其签入版本控制以确保依赖版本在整个开发团队中保持一致。
锁定文件与 requirements.txt
锁定文件和 requirements.txt 都处理依赖关系,但它们有不同的用途:
前者,即 Lock 文件,是开发的重要组成部分,因为它们有助于建立可重复的构建。requirements.txt 文件比 Lock 文件简单一些,通常只包含直接依赖项,因为它们在 Python 工具中被更广泛地认可,并且可以作为与不使用 UV 的最终用户共享/部署代码的一种方式。你可以使用 UV lock 文件进行开发,并在部署时生成如下的 requirements.txt 文件来维护两者:
uv export -o requirements.txt
使用 UV 进行高级依赖管理
UV 提供了复杂的方法来管理依赖关系:
更新依赖项
添加命令可用于更新、更改约束或指定现有依赖项的确切版本:
安装最新版本:
uv add requests
安装特定版本:
uv add requests=2.1.2
改变约束边界:
uv add 'requests<3.0.0'
使依赖关系特定于平台:
uv add 'requests; sys_platform="linux"'
添加可选依赖项
可选依赖项是核心功能不需要但特定功能需要的包(例如,Pandas 的 excel 或 plot 附加功能)。
首先,安装核心包:
uv add pandas
然后,添加其可选依赖项:
uv add pandas --optional plot excel
这些将在你的 pyproject.toml 中的 [project.optional-dependencies] 下列出。
依赖组
依赖项组允许你组织依赖项(例如,开发、测试和文档依赖项)以保持生产依赖项分离。
要将新的依赖项安装到特定组中,你可以使用 –group 标志:
uv add --group group_name package_name
用户可以使用 –group、–only-group 和 –no-group 标志来进一步控制安装哪些组。
从 PIP 和虚拟环境切换到 UV
从 pip 和 虚拟环境 迁移到 UV 几乎是无缝的。这是因为 UV 的构建遵循了现有的 Python 打包标准。
转换现有的虚拟环境项目
如果你已有项目:
pip freeze > requirements.txt
接下来,你将在同一目录中启动一个新的 UV 项目:
uv init.
现在你可以从需求文件安装依赖项:
uv pip install -r requirements.txt
替换常见的 pip/虚拟环境 命令
以下是替换常见 pip/虚拟环境 命令的快速参考:
迁移完成后,你可以安全地删除旧的 虚拟环境 目录。如果你发现需要回退到传统的 pip 命令,你可以随时使用 UV 内置的 pip 兼容层。
写在最后
UV 在众多 Python 包管理器中脱颖而出,与之前的工具相比,它提供了一种现代、快速且高效的包管理替代方案。UV 的主要优势包括:
令人难以置信的性能(比 pip 快 10-100 倍)。 与当前 Python 打包标准兼容。 内置虚拟环境支持。 极其高效的依赖关系解析和锁文件支持。 内存占用和资源消耗小。
无论你是启动一个全新的项目还是升级现有的项目,UV 都是一个可靠的解决方案,可以改善你的 Python 开发工作流程。而且,由于它与现有的工具和流程兼容,对于希望在不中断现有工作流程的情况下将其开发工具链带入 21 世纪的开发人员来说,这是一个简单的选择。
作为开发者,我们生活在一个不断发展的环境中。UV 等工具正是 Rust 等现代语言如何提升开发者体验的典范。同时,它还保留了 Python 开发者所依赖的易用性和可访问性。
既然你已经了解了 UV 作为 Python 包管理器的显著优势,不妨在你的下一个项目中尝试一下。请务必查看官方 GitHub 仓库,了解最新更新或贡献。此外,请与开发社区分享你的经验,以帮助扩大 UV 的采用率并促进其未来的增强。