「TF」01 uv - “下一代Python包管理器”
Greetings! ¶
嗨!这里是阿乎的博客!(> ▽ <) /~
今天我们来介绍一下uv
,这个被称为“下一代Python包管理器”的工具。
1. What is uv
? ¶
根据官网的介绍,uv
是"An extremely fast Python package and project manager, written in Rust.",即“一个用Rust
编写的极快的Python包和项目管理器”。
Rust
是一个近年来兴起的新一代系统编程语言,以强调“内存安全+高性能”的而著称。
自 Linux 6.1(2022年12月)起,Rust
被首次合并进主线内核,用于处理实验性代码和驱动。尽管目前代码比例很小,但它确实是 Linux 内核迈向“下一代 C 系列”语言方向的一大步。
下图是官网介绍的uv
的亮点:
2. Why uv
? ¶
至少对我来说,uv
实在是非常让人惊艳!
2.1. Speed ¶
我认识Rust
比认识uv
要早。当时Rust
一直饱受争议——一个被很多人鼓吹很强的语言却并没有很多实际应用,即便是部分放入Linux内核的行为也并非能让人信服。
然而,uv
的出现却让我真正认识到Rust
的强大。
Installing Trio’s dependencies with a warm cache
上图是uv
在安装Trio
库时的速度对比。可以看到,uv
的速度远超其他传统工具!按官方的说法,“10-100x faster than pip”(比pip快10-100倍)!
2.2. All in one ¶
uv的另一个亮点是它的“全能”,一个工具替代一堆工具(参考 GitHub:https://github.com/astral-sh/uv):
-
pip
:uv pip install ...
-
virtualenv
:创建.venv
等当前目录下的虚拟环境(uv venv
) -
pip-tools
:生成.lock
文件并确保依赖一致性(uv lock
,uv sync
) -
poetry
/pdm
:项目初始化、添加/移除依赖、运行脚本和工具等 -
pipx
:用uv tool
和uvx
快速执行 CLI 工具(如ruff、black
)
3. How to play with uv
? ¶
具体的使用方法可以参考官网的文档,但我会简单介绍一下基本用法。
3.1. Install uv
¶
安装uv
有两种主要方法:
- 使用
pip
安装pip install uv
- 系统级安装
- Windows:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
- MacOS and Linux:
curl -sSfL https://astral.sh/uv/install.sh | sh
- Windows:
⚠️注意:由于信息时效性,以上命令不一定长期有效。
建议参考官网的安装说明获取最新的安装方法。
卸载详见官网的卸载说明。
3.2. Update uv
¶
更新uv
非常简单,只需运行以下命令:
- 如果是使用
pip
安装的:pip install --upgrade uv
- 如果是系统级安装的:
uv self update
3.3. uv
and virtual environments ¶
uv
的对于Python的管理 ¶
与Conda
不同,uv
是“枪弹分离”式地管理Python可执行文件和包依赖的。
Conda
的每个虚拟环境都是一个独立的封闭空间,包含:
- 独立的一套 Python 可执行文件(如Windows上的
python.exe
) - 所有依赖库(包括 Python 和非 Python 包)
uv 的管理方式则是“分层”结构:
- Python 各版本只需 全局缓存一份(
~/.cache/uv/pythons
) - 每个项目只在
.venv
中保存当前项目需要的依赖(库文件), - Python 是从全局引用(软链接/绑定),而不是复制一份
这种特别的方式有效地减少了磁盘空间的占用!让我这样有“磁盘洁癖”的人感到非常舒适!
创建虚拟环境 ¶
你只需要在你的项目目录下运行以下命令即可创建一个虚拟环境:
uv venv # 在当前目录下的.venv创建一个虚拟环境(没有名字)
uv venv myenv # 在当前目录下的myenv创建一个叫做myenv的虚拟环境(位置为./myenv)
uv venv --python 3.11 # 指定Python版本创建虚拟环境(默认使用全局最新版本)
举个例子,以下代码会在当前目录下创建一个名为tmp_env
的虚拟环境,并使用Python 3.11版本:
uv venv tmp_env --python 3.11
注意:如果指定的版本并没有安装,
uv
会自动下载并安装对应版本的Python。
激活&退出虚拟环境 ¶
- 如果使用的是默认的
.venv
目录(通过uv venv
命令创建),那么之后的任意uv
命令都会自动激活这个虚拟环境。 - 还有一种通用方法,即使用创建虚拟环境时自动生成的激活脚本
<env_name>/Scripts/activate
- 举个例子,在Windows上,你可以运行以下命令来激活名为
tmp_env
的虚拟环境:
.\tmp_env\Scripts\activate
- 在Linux或MacOS上,你可以运行以下命令:
./tmp_env/bin/activate
退出虚拟环境倒是比较方便,无论是哪一个系统,你只需运行以下命令即可:
deactivate
3.4. Install packages ¶
在说明如何安装包之前,我们必须得了解一个东西:pyproject.toml
它是 Python 官方(PEP 518)定义的项目配置文件,类似于:
- JavaScript 项目的
package.json
- Rust 的
Cargo.toml
- 或者 Conda 的
environment.yml
pyproject.toml
文件包含了项目的元数据(如项目名称、版本、作者等。是的,项目其实是应该有名称的!)、依赖关系和构建配置等信息。
与虚拟环境的概念不同,它是项目级别的配置文件。(当然,它也会用于管理虚拟环境的依赖,即该文件中的dependencies
字段)
通过uv
有两种方法来安装包:
- pip法:(不推荐)
这种方式类似于传统的uv pip install <package_name>
pip
,但它并不会写入pyproject.toml
文件。 - uv add法:(推荐)
这种方式会自动将包添加到uv add <package_name>
pyproject.toml
文件中,并且会处理依赖关系。
同时,当使用uv add法安装包时,uv
还会更新一个名为uv.lock
的文件,这个文件类似于npm
的package-lock.json
,用于锁定依赖版本,记录了项目所有依赖的精确版本(包括递归依赖)。
uv sync
命令会根据uv.lock
文件将.venv
环境中的安装状态完全调整成 lockfile 中记录的内容。
3.5. Summary ¶
简单总结一下uv
的基本用法:
- 创建虚拟环境:
uv venv
或uv venv <env_name>
,可以用--python
指定Python版本。 - 激活虚拟环境:通过
<env_name>/Scripts/activate
的脚本 - 退出虚拟环境:
deactivate
- 安装包:
- 使用
uv pip install <package_name>
(不推荐) - 使用
uv add <package_name>
(推荐)
- 使用
4. Use uv
in your projects ¶
4.1. Initialize a project ¶
实际上,我们还有一个uv init
命令可以用来初始化一个新的项目,这个命令会自动创建pyproject.toml
等关键文件,让你的新项目更加规范。
uv init my_project
这个命令会在当前目录下创建一个名为my_project
的目录,并在其中生成所有项目基本文件:
my_project/
├── .gitignore # git 忽略文件
├── .python-version # 记录 Python 版本的文件,以明文记录该项目使用的 Python 版本
├── main.py # 主程序文件
├── pyproject.toml # 项目配置文件
└── README.md # 项目说明文件
此时,初始化并未完成!
接下来我们可以使用uv run main.py
来运行项目的主程序。
在此之后项目的目录结构会变成这样:
my_project/
├── .venv # 虚拟环境目录
├── .gitignore
├── .python-version
├── main.py
├── pyproject.toml
├── README.md
└── uv.lock # 锁定依赖版本的文件
也就是说:在第一次通过uv
运行项目后,uv
会自动创建一个虚拟环境,并将其与项目关联起来。
4.2. Add dependencies ¶
之后我们就可以使用uv add <package_name>
来安装项目所需的依赖包了。
现在,检查一下你的
pyproject.toml
文件和uv.lock
文件。或许可以考虑截图便于之后对比。
让我们以rich
库为例
uv add rich
之后可以观察到:
pyproject.toml
文件中会自动添加rich
于dependencies
字段中uv.lock
文件中会记录rich
的具体版本和依赖关系(会有很多递归依赖,比如说rich
依赖于pygments
、mdurl
等等).venv
目录中会安装rich
及其所有依赖
让我们修改一下main.py
文件,添加一些使用 rich
的代码:
from rich import print
def main():
print("Hello, uv!") # 不使用 rich 美化输出
print("[bold green]Hello, uv![/bold green]") # 使用 rich 美化输出
if __name__ == "__main__":
main()
之后再运行这个项目:
uv run main.py
那么你就可以看到两种颜色的输出了:
5. 结语 ¶
我在写这篇文章的时候,还并没有很多的uv
使用经验(毕竟conda
和pip
已经用三四年了,没有第一时间尝试uv
),但我意识到越来越多的项目开始使用uv
作为包管理器。因此第一时间写下这篇文章,分享给大家。
希望能帮到大家!
Have fun! 😉