Featured image of post UV如何使用

UV如何使用

我操了老铁,这uv怎么用

你需要知道的

uv 是一个非常强大的工具,可以工程化一个python项目,而不只是作为一个虚拟环境管理工具。1

astral-sh/uv

🚀 一个工具替代 pip、pip-tools、pipx、poetry、pyenv、twine、virtualenv 等

⚡️ 比 pip 快 10-100 倍

🗂️ 提供全面的项目管理功能,包含通用锁文件

❇️ 运行脚本,支持内联依赖元数据

🐍 安装和管理 Python 版本

🛠️ 运行和安装 以 Python 包形式发布的工具

🔩 包含 pip 兼容接口,在熟悉 CLI 的同时获得性能提升

🏢 支持 Cargo 风格的工作区用于可扩展项目

💾 磁盘空间高效,通过全局缓存实现依赖去重

⏬ 无需 Rust 或 Python 即可通过 curl 或 pip 安装

🖥️ 支持 macOS、Linux 和 Windows

在此以写一个项目的方式来介绍一下uv的使用方法,当然了,uv的功能远不止这些。

安装UV

安装uv非常简单,可以通过pip安装:

1
pip install uv

然而这种方法并不推荐,因为它会将uv安装在全局环境中,可能会导致版本冲突和权限问题。

uv官方提供了二进制版本,可以一键安装

  • linux/MacOS: curl -LsSf https://astral.sh/uv/install.sh | sh
  • windows: powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"

这时,你可能需要将uv添加到path中,别担心,uv会提示你如何操作。

使用UV

使用uv创建一个python项目

在你想要创建项目的目录下,运行以下命令:

1
uv init

可以看到,uv会在文件夹下自动帮你初始化一个项目,包含git,pyproject.toml,uv.lock等文件。

运行项目

如果你运行python ./main.py,你就会收到uv的问候。

main.py,或是 src 目录下的其他 Python 文件中,你可以开始编写你的项目代码了。

添加依赖

在我们coding过程中,通常需要添加一些第三方的依赖,如httpx,我们可以直接在代码中添加依赖:

1
uv add httpx

此时,uv做了以下事情

  1. 自动为你创建虚拟环境到.venv下
  2. 安装httpx到虚拟环境中
  3. 将httpx添加到pyproject.toml的dependencies中
  4. 将httpx添加到uv.lock中

运行程序

在上文中,我们使用python ./main.py来运行项目,但是事实上我们这里使用的是全局的python解释器,而不是uv创建的虚拟环境中的python解释器。 因此,我们需要使用.venv中的python解释器来运行项目:

1
uv run main.py

这样,uv会自动使用.venv中的python解释器来运行main.py,并且会自动加载项目的依赖。 如果需要手动进入虚拟环境中,你需要手动激活

  • windows: .venv\Scripts\activate
  • linux/MacOS: source .venv/bin/activate

此时终端的上下文已经切换到虚拟环境中,你可以直接使用python来运行项目了。

1
python main.py

手动同步

在一些情况下,我们可能使用uv pip install来安装了一些包,但是uv并不会自动将这些包添加到pyproject.toml和uv.lock中,此时可能会导致pyproject.tomluv.lock中的依赖和实际安装的依赖不一致,最终导致项目无法运行。 因此,我们需要手动同步镜像,方法如下:

1
uv sync

此命令会将pyproject.tomluv.lock中的依赖同步到虚拟环境中,确保项目的依赖和实际安装的依赖一致。

一些常见的问题

uv pippip 的区别

事实上,pip 也只是 Python 的一个包,而不是独立的组件。你甚至可以使用 pip 来安装 pip

uv pip 是 uv 重写的 pip,具有 pip 的功能,但更高效。同时,uv pip 会自动使用当前项目下的虚拟环境来安装依赖,而不是全局环境。

为什么我使用uv创建了虚拟环境,但是在环境里用pip安装的包却失踪了

正如上文所述,pip只是python的一个包,而不是独立的组件。当你在uv创建的虚拟环境中时,由于uv并不会一并安装pip等组件,导致你在虚拟环境中使用pip其实是全局环境中的pip,自然而然,你安装的包就会安装在全局环境中,而不是虚拟环境中。

为什么我的pip包下载速度这么慢

uv并不会使用你系统设置的pip的pypi索引,因此你需要自行为uv设置一个pypi索引,方法如下:

为项目使用单独的pypi索引

在你的项目的pyproject.toml中添加以下内容:

1
2
3
[[tool.uv.index]]
name = "tencent"
url = "https://pypi.tuna.tsinghua.edu.cn/simple"

设置全局的pypi索引

Windows

按下 Win + R,输入 %APPDATA%\uv\uv.toml,回车后在打开的文件中添加以下内容:

1
2
3
[[index]]
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
default = true
Linux/MacOS

在你的用户目录下创建一个uv文件夹,在该文件夹下创建一个uv.toml文件,添加以下内容:

1
2
3
[[index]]
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
default = true

我为什么要使用UV

uv解决了以下问题

全局环境冲突

在开发两个不同的项目时,可能会出现两个项目依赖的库版本不兼容的情况。 比如项目A 需要pydantic 2.0,而项目B 需要pydantic 3.0,这时如果直接安装在全局环境中,就会导致冲突,无法同时满足两个项目的需求。

后来出现了虚拟环境工具(如 virtualenv、venv),可以为每个项目创建一个独立的环境,避免了全局环境冲突的问题。但是这些工具在管理依赖和版本方面仍然存在一些不足,比如需要手动激活环境、安装依赖等。

python 的虚空依赖

pip 是 Python 的包管理工具,他很好用。但是如果形成了下列的依赖链条

1
A -> B -> C -> D

当我们安装 A 时,pip 会自动安装 B、C、D 这三个依赖包。 但是当我们卸载 A 时,pip 只会卸载 A,而不会自动卸载 B、C、D 这三个依赖包。 这就导致了所谓的「虚空依赖」,即一些包被安装了但没有被任何项目依赖,最终占用磁盘空间。

项目化

在以往,经常会碰见一个.py文件就是一个项目的情况,很难声明这个项目需要哪些依赖,或者说这个项目需要什么样的环境。

后来有了 requirements.txt,可以声明项目的依赖,但是这个文件只能声明依赖的名称和版本,无法声明依赖的来源、安装方式等信息。

使用 Hugo 构建
主题 StackJimmy 设计