mylogo

退役程序员的茶室 RetiredCoder.cn

← 返回上一页

UV学习笔记:闪电级Python包管理

最近在学习MCP时接触到了uv这个工具,感觉它既强大,又好用,于是整理了一期uv使用视频教程,已在视频号「退役程序员」中发布,这次我将学习中总结的笔记一并分享,供大家参考。

💠 UV基础

🔘 什么是UV

uv是一个现代的Python包安装器和解析器,旨在成为pippip-tools的快速替代品,提供更快的依赖解析和安装速度,并支持灵活的依赖管理。uv的目标是解决Python生态系统中长期存在的依赖管理痛点,例如速度慢、依赖冲突难以解决等问题。 ### 🔘 安装UV

具体安装方式请参考其官网说明:

https://docs.astral.sh/uv/getting-started/installation/

本机上我用的是:

brew install uv

查看可用的参数和说明文档,安装后在命令行输入:

uv

🔘 安装不同版本的python

查看可安装和已安装的python列表:

uv python list

安装某个版本的Python

uv python install 3.12

查找路径

uv python find 3.12

卸载

uv python uninstall 3.12

💠 在没有设置持久虚拟环境时使用uv

🔘 运行代码

我有一个简单的main.py文件来打印正在使用的Python版本和路径:

import sys
print(sys.version)
print(sys.executable)

用uv来运行它,可以输入以下命令:

uv run main.py

🔘 选择特定python版本运行

uv run --python 3.11 main.py

🔘 确保依赖库可用

如果我的代码中引入了如requests这样的外部库,例如:

import sys
import requests
print(sys.version)
print(sys.executable)

如何来确保依赖库可用呢?这里有三种方法:

方法1: 命令行中添加--with requests

运行下面的命令:

uv run --with requests --python 3.11 main.py

方法2: 内联脚本元数据中修改dependencies = []

先用下列命令为main.py加入内联脚本元数据代码:

uv init --script main.py --python 3.12

这会自动在代码前加入内联脚本元数据:

# /// script
# requires-python = ">=3.12"
# dependencies = []
# ///

import sys
import requests
print(sys.version)
print(sys.executable)

# /// script# ///之间的内容被称为内联脚本元数据,它允许将脚本的元数据(例如本例中所需的Python版本和依赖)直接嵌入到脚本文件的顶部。这部分脚本告诉uv如何在后台正确地准备和运行main.py所需的Python环境和依赖。

如果还没有main.py文件,则会自动生成一个main.py文件:

# /// script
# requires-python = ">=3.12"
# dependencies = []
# ///


def main() -> None:
    print("Hello from main.py!")


if __name__ == "__main__":
    main()

在其中手动修改# dependencies = [],变为:

# dependencies = ["requests"]

方法3 使用uv add命令

本例中,可以直接使用下面命令添加:

uv add --script main.py "requests"

请注意,这时我们并没有创建一个持久的虚拟环境来运行程序,这时的uv会为main.py动态地创建一个临时的、隔离的虚拟环境。它是临时的按需创建,uv 会智能地缓存这个环境,只要脚本的依赖或Python版本没有改变,就会在后续运行同一个脚本时复用它。

💠持久虚拟环境下的Python项目

🔘 创建项目目录

创建一个名为newproject的新项目(如在本课对应视频课程中),可输入如下命令:

uv init newproject

这会直接创建一个名为newproject的项目目录

或者,也可以在一个已存在的目录中输入uv init来创建(默认创建的项目是个应用,省略参数–app)

1. pyproject.toml

这是Python项目的核心配置文件,uv也会使用它来识别该项目的根目录。 项目初始化后的toml文件内容一般是这样的:

[project]
name = "projectname"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = []
  • name: 该项目名称。这对于标识项目至关重要,尤其是在发布包时。

  • version: 该项目当前版本。这有助于跟踪更改和发布。

  • description: 该项目功能的简短摘要。

  • readme: 指定该项目 README 文件的路径。

  • requires-python: 指定该项目兼容的 Python 版本。uv在创建环境或安装依赖项时会遵守这一点。

  • dependencies: 项目运行所需的直接依赖项列表。这些通常指定为包名,可带有版本约束。uv将使用它来解析和安装该项目的依赖。

2. .python-version

用于指定项目使用的 Python 版本。 告诉uv在创建项目虚拟环境时应该使用哪个Python版本。这确保了项目的Python环境一致性。

3. .venv目录

这是一个隐藏目录,包含了项目虚拟环境。这是一个与系统其他Python环境隔离的独立Python环境。uv会将本项目依赖包安装到这个目录中。这种隔离有助于避免不同项目之间的依赖冲突,并确保项目在不同机器上运行的一致性。

4. README.md

这是一个Markdown格式的文本文件,通常用于项目的说明。提供项目的简介、安装说明、使用指南、贡献方式等信息。

5. .gitignore

这是一个文本文件,用于指定Git在版本控制中应该忽略的文件和目录。告诉Git哪些文件或目录不应该被提交到版本库中,例如虚拟环境 (.venv目录)、编译生成的文件、临时文件、敏感信息等。这有助于保持代码仓库的整洁。

6. main.py或项目同名.py文件 (可选)

根据uv init的具体选项(例如 --app--package)生成。

7. uv.lock (在首次运行 uv adduv sync 后生成)

这个文件不会在uv init时立即生成,而是在你首次添加依赖 (uv add) 或同步环境 (uv sync) 时创建。uv.lock 是一个锁文件,它记录了项目中所有依赖包(包括直接依赖和间接依赖)的精确版本。这个文件确保了项目在不同机器和不同时间上的可复现性。它应该被提交到版本控制中,以保证团队成员和部署环境都使用一致的依赖版本。

🔘 添加依赖库

在项目目录下,也可以像前面方法3中提到过的uv add命令添加:

uv add requests

如果此时项目目录中还没有创建虚拟环境,运行后虚拟环境会自动建立起来。(或者在项目目录中用uv venv命令来生成)

也可以在toml文件的dependencies = []中手动添加依赖的库,之后再运行:

uv run main.py

系统会自动运行un sync来同步(这个命令也可以输入命令行运行), 它也会自动生成uv.lock文件(或者用命令uv lock来生成) ### 🔘 卸载依赖库

如果要删除项目的依赖库requests,可以:

uv remove requests

🔘 修改Python版本

在安装依赖库时有时可能需要更低版本号的Python,这是需要降低项目Python环境的版本,可在toml文件中修改requires-python的值,例如requires-python = ">=3.8,<3.11",这时要确保uv环境中已经安装过较低版本的Python,可用命令uv python list来确认是否已安装。

🔘 显示项目依赖结构

uv tree

🔘 查看安装了哪些包

uv pip list

🔘 迁移旧有项目

如果是一个旧方法创建的项目文件夹,可利用requirements.txt将其变成uv环境:

uv add -r requirements.txt