Skip to content

UV:Rust 重写的快速 Python 包管理器

约 2502 字大约 8 分钟

PythonRustShell

本文编写中

2025-07-17

「Rust 重写一切,UV 管理 Python 的一切。」在 Python 生态中,包管理一直是一个复杂且多样化的问题。随着项目的增长和依赖关系的增加,管理这些包变得越来越具有挑战性。UV 作为一个新兴的包管理工具,旨在简化这一过程,并提供更高效的解决方案。

Windows 用户使用管理员模式的 PowerShell 执行下面的命令安装即可,如果有报错问问 GPT 就可以了,多半是权限的问题。

powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

其他方式和操作系统安装参考:https://docs.astral.sh/uv/getting-started/installation/#standalone-installer

简单尝试

Python 管理

uv python+ 命令,一般是先 list 看哪些版本可以下,find 看安装了什么版本,install 安装,uninstall 卸载,pin 特定版本到项目。

安装最新版 cpython

uv python install [版本号] --reinstall(可选,覆盖安装)

升级 python 版本

uv python upgrade

代理执行

前提是.py 文件中导入的包为 标准类库,例如 import osimport sys 等等

uv run <python 文件 > [参数]

有特定依赖项使用以下命令:

uv run <python 文件 > --with < 依赖项 > [参数]

显式声明依赖

2023 年 10 月,python 官方发布了 PEP 723,引入了声明式内敛元数据以及 pyproject.toml 文件来声明项目的依赖项。

初始化

uv init --script <python 文件 > --python <python 版本 >

声明脚本依赖,这里向 example.py 文件添加了 requestsrich 这两个依赖项,版本限制为小于 3 的版本。

uv add --script example.py 'requests<3' 'rich'

修改下载地址(包索引)

如果你想使用其他镜像源,可以通过以下命令修改包索引地址:

uv add --index "https://example.com/simple" --script example.py 'requests<3' 'rich'

会一并写入 pyproject.toml 文件中。

# [[tool.uv.index]]
# url = "https://example.com/simple"

到这里,我们就可以看出它的长处了,可以显示定义下载源,版本依赖,甚至可以指定脚本文件。

锁定脚本依赖

与项目不同,脚本依赖是指特定脚本所需的依赖项。可以通过以下命令锁定脚本依赖:

uv lock --script example.py

生成的结构如下

Example

test.py

test.py.lock

test.py
import site
import sys
import ultralytics
test.py.lock
version = 1
revision = 2
requires-python = ">=3.13"

使用不同 python

uv run <python 文件 > --python <python 版本 > [参数]

UV 工具

uvx

只有当在无关紧要的测试、扁平化项目中用这个比较合适,uvx 等价于下面的命令:这样做是为了预先测试检查兼容 python 包版本,你知道的,python 的包管理就和重庆的天气一样糟糕(

uv tool run
$ uvx pycowsay nb

  --
< nb >
  --
   \   ^__^
    \  (oo)\_______
       (__)\       )\/\
           ||----w |
           ||     ||

这个用的比较少,暂时写到这里。链接:https://docs.astral.sh/uv/guides/tools/#running-tools

项目管理 常用

uv init hello-world
cd hello-world

生成的目录结构如下:

hello-world

.gitignore

.python-version

README.md

main.py

pyproject.toml

.gitignore
# Python-generated files
__pycache__/
*.py[oc]
build/
dist/
wheels/
*.egg-info

# Virtual environments
.venv
.python-version
3.13
README.md
main.py
def main():
    print("Hello from hello-world!")


if __name__ == "__main__":
    main()
pyproject.toml
[project]
name = "hello-world"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = []

项目结构

.venv

Scripts

include## 包含的头文件

lib## 所有的包安装位置

...

python.exe## 当前版本 python 执行程序

pyvenv.cfg

.python-version

README.md

main.py

pyproject.toml

uv.lock

pyproject.toml

查看 所有字段

pyproject.toml
[project]
name = "hello-world" ## 项目名称
version = "0.1.0" ## 项目版本
description = "Add your description here" ## 项目描述
readme = "README.md" ## 项目说明文件
requires-python = ">=3.13" ## 需要的 python 版本
dependencies = [] ## 依赖项列表

现在我们来试试 安装 yolo 的依赖项,PYPI 的镜像站点下载最好把代理关了或者设置镜像。

install.sh
uv add ultralytics

20250719.png

非常快,10 秒内完成几百兆的文件下载和索引!(不过网速足够可能才行)

变化如下:

pyproject.toml
[project]
name = "hello-world"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.13"
dependencies = [
    "matplotlib>=3.10.3", 
    "tqdm>=4.67.1", 
    "ultralytics>=8.3.168", 
]

.python-version

告诉项目使用的 Python 版本号,初始化后自带,也可自定义

.venv

项目的虚拟环境,即与系统其余部分隔离的 Python 环境。这是 uv 将安装项目依赖项的位置。

uv.lock 重要

uv.lock 是一个跨平台的 lockfile,其中包含有关项目依赖项的确切信息,类似与 npm 中的 package.lockpnpm.lock, 由 uv 自动化控制和生成,不要修改它。它可以:

  • 声明项目的开发平台
  • 声明项目所需的 Python 版本
  • 声明包及其依赖的下载地址、文件哈希等

文件哈希

通过哈希校验算法确认包未被篡改,保障包的完整性和安全性。

这样做的好处是让不同平台的开发者在安装依赖时获得相同的结果,确保项目在不同环境中的一致性。(哇,安装包很头疼的好吗?)

坏处是若下载地址失效或包被删除,可能会导致安装失败,可以 [手动尝试修改下载地址](/article/20250717/# 修改下载地址 - 包索引)。

pyproject.toml

添加、移除依赖

add、remove

uv add requests
uv remove requests

# Specify a version constraint
uv add 'requests==2.31.0'

# Add a git dependency, 手动指定
uv add git+https://github.com/psf/requests

从 requirements.txt 中同步

在常见的 pip 管理的项目中,我们会用到 requiremts.txt 来管理项目,uv 支持迁移

uv add -r requirements.txt -c constraints.txt

升级某个包

正常的流程是先锁定其他包的版本,再执行某个包的升级任务

uv lock --upgrade-package <package>

查询项目版本

同步依赖

一般而言,写好代码后为了运行起来,新增的依赖我们自然而然就把依赖装好了,比如 uv add。但是如果是团队协作中,其他人可能没有安装你新增的依赖(反之亦然),这时候就需要同步依赖了。

uv sync # 同步依赖到 uv.lock 和 pyproject.toml
.venv\Scripts\activate ## windows
source .venv/bin/activate ## linux/macOS
flask run -p 3000
python example.py

激活环境后,无需再使用 uv 前缀,直接使用 python 命令即可运行脚本。

造轮子

uv build

默认在当前目录生成 dist 目录,里面包含了打包好的文件。

dist

.venv

Scripts

include

lib

python.exe

pyvenv.cfg

dist

hello_world-0.1.0-py3-none-any.whl// wheel 包,也就是所谓的轮子

hello_world-0.1.0.tar.gz// 源码包

hello_world.egg-info// hutch 包信息

dependency_links.txt

PKG-INFO

requires.txt

SOURCES.txt

top_level.txt

main.py

pyproject.toml

uv.lock

README.md

.python-version

.gitignore

LICENSE

发布包

升级项目版本号

uv version n.e.w

平级升级,uv 划分的标准从大到小为:major, minor, patch, stable, alpha, beta, rc, post, and dev

# 从稳定版到预发布版
uv version --bump patch --bump [alpha/beta/rc/post/dev]

# 预发布版的内部升级
uv version --bump [alpha/beta/rc/post/dev]

# 预发布版到稳定版
uv version --bump stable

同步注意

执行 uv version 后会自动更新 pyproject.tomluv.lock 文件中的版本号。不升级请执行 --frozen 参数

迁移

pip2uv

我们都知道,pip 使用 requirements.txt 来管理依赖。例如,写入当前项目的依赖使用:

环境隔离

考虑使用 venv 虚拟环境来隔离项目依赖,避免某个 Python 版本全局安装包的冲突(想哭了😭)。

python -m venv
source .venv/bin/activate
pip ...

其中一种管理依赖的方式是 pip-compile 编译规则集 requirements.in 文件

例如,requirements.in 文件内容如下:

requirements.in
fastapi
pydantic>2

表示 fastapi 无版本约束, pydantic 版本大于 2.0.0。

执行下面的命令来生成 requirements.txt 文件:

pip-compile requirements.in -o requirements.txt
requirements.txt

这个等同于 uv pip compile ,也是 pip-tools 中的 pip-compile 命令。


另外一种比较不常见的方式是使用 pip freeze 命令来生成当前环境的依赖列表。

pip freeze > requirements.txt
requirements.txt
annotated-types==0.7.0
anyio==4.8.0
fastapi==0.115.11
idna==3.10
pydantic==2.10.6
pydantic-core==2.27.2
sniffio==1.3.1
starlette==0.46.1
typing-extensions==4.12.2

豪了,有以上的思路,我们就可以:

  1. 划分各种依赖环境

    比如项目有 dev | prod | staging 等环境,我们可以将依赖分为不同的文件,例如 requirements-dev.inrequirements-prod.in 等。

  2. 编写这些文件中的特殊依赖

    写好后分别保存到 requirements-dev.inrequirements-prod.in 文件中。

  3. 使用 uv pip compile 命令编译每个环境的依赖

    uv pip compile requirements-dev.in -o requirements-dev.txt
    # 或者 pip-compile requirements-dev.in -o requirements-dev.txt
    uv pip compile requirements-prod.in -o requirements-prod.txt
  4. 安装依赖

    pip install -r requirements-dev.txt
    pip install -r requirements-prod.txt

上面讨论的同一个项目中不同开发环境的依赖管理。再扩展下,不同的操作系统也是一样的。

不过 uv 支持跨平台解析,非常方便,比如 tqdm

tqdm

两个平台的解析为

Linux
tqdm==4.67.1
    # via -r requirements.in

colorama: Windows 平台下的 tqdm 需要 colorama 包来支持终端颜色输出

这样每个平台间是不兼容的,

如果使用 uv 的 universal 选项 ,则会声明 colorama 的平台:

uv pip compile --universal requirements.in
requirements.txt
colorama==0.4.6 ; sys_platform == 'win32' # 这里就声明了
    # via tqdm
tqdm==4.67.1
    # via -r requirements.in