Python 的生态让人能够很快写出实用脚本,但切换解释器版本、选择虚拟环境工具、维护依赖文件和安装命令行工具,常常又变成另一项工作。刘家财在原文中正是从这种体验出发介绍 uv:一个用 Rust 编写、试图把多种 Python 包管理任务统一起来的工具。
本文核查整理自刘家财的 《uv :新一代的 Python 包管理工具》。原文发表于 2025-08-03,页面显示更新于 2025-11-02;本稿于 2026-10-05 核对全文,并用当前 uv 官方安装和项目指南核对关键措辞。原文所引“比 pip 快 10–100 倍”是项目宣传中的比较范围,不是本文测试结果,也不适用于每一组依赖、网络与缓存条件。

安装 uv:先核对下载来源
原文的 Unix 安装命令使用 https://install.astral.sh 并直接管道给 sh。截至核对日,官方安装文档列出的安装器地址为 https://astral.sh/uv/install.sh,同时提供 Windows、包管理器及发行包等方式。安装器能够修改用户目录和 shell 配置,因此不能把远程内容下载后立即执行当成无需审核的操作。
编者修订:下面把原文的一行管道改成“先下载到文件,再检查同一份文件,确认后执行”。它仍然需要你信任来源并理解脚本行为,不会自动证明安装器安全。没有下载或运行安装器:
curl -LsSf https://astral.sh/uv/install.sh -o uv-install.sh
less uv-install.sh
# 检查上述文件内容及来源后,才执行同一份本地文件:
sh uv-install.sh
uv --version
原文使用的命令是 macOS/Linux shell 语法,不适合原样粘贴进 PowerShell。原文还提示把 ~/.local/bin 加入 PATH:
export PATH="$HOME/.local/bin:$PATH"
是否需要手动设置,应以安装器输出和当前安装方式为准;不要重复向启动文件追加配置。官方文档提供的版本化安装器也可以用于固定版本,但固定版本不等于完成了完整性和供应链审核。
用同一工具管理多个 Python 版本
有些包和项目对 Python 版本有明确要求。uv 可以安装解释器,并在项目目录记录所用版本。原文使用 Python 3.12.4 演示:
uv python install 3.12.4
uv python pin 3.12.4
uv python list
install 安装指定解释器,pin 在当前目录创建或更新 .python-version,list 查看解释器信息。原文说明 Unix 上常见的管理目录是 ~/.local/share/uv/python/,实际位置可能随操作系统与环境配置不同。
版本提示:3.12.4 是原文的历史演示版本,不代表截至 2026 年的推荐补丁版本。新项目应结合依赖兼容性和受支持的安全更新选定版本。原文还列出 uv python uninstall 3.12.4;它会移除 uv 管理的对应解释器,只有确认没有项目依赖该安装后才应使用,本稿没有执行卸载。
项目工作流:声明、锁定、同步
传统虚拟环境的常见步骤是先创建、再激活,然后安装依赖:
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt
deactivate
uv 把项目环境纳入命令管理。执行 uv init 创建项目后,原文展示的初始文件包括 .gitignore、.python-version、README.md、main.py 和 pyproject.toml。执行 uv add 等需要同步环境的操作后,会产生 .venv 和 uv.lock。初始化生成哪些文件可能随版本和初始化选项变化。
项目目录/
├── .python-version
├── README.md
├── main.py
├── pyproject.toml
├── uv.lock
└── .venv/
这里有三类不同的事实:pyproject.toml 记录项目元数据和依赖约束;uv.lock 记录解析后的依赖版本等锁定信息;.venv 是当前机器上的实际虚拟环境。声明、解析结果和环境互有关联,但不能相互替代。
原文的项目声明示例为:
[project]
name = "hello-world"
version = "0.1.0"
description = "Add your description here"
readme = "README.md"
dependencies = []
uv 自身的项目配置通常放在 [tool.uv] 中,简单项目不需要先填写大量配置。锁文件类似前端生态中的 package-lock.json 或 yarn.lock,用于保存已解析的依赖关系。应当把项目声明与锁文件共同纳入项目的版本管理;虚拟环境仍需在目标机器上重新同步。
添加、删除和导入依赖
uv add requests
uv remove requests
# 以下固定版本来自原文,仅用于说明约束语法:
uv add 'requests==2.31.0'
# 原文的 Git 依赖示例:
uv add git+https://github.com/psf/requests
# 从已有的依赖文件导入:
uv add -r requirements.txt
# 根据项目配置与锁定状态同步实际环境:
uv sync
uv add 和 uv remove 会维护项目声明、锁文件以及相应环境。手动修改 pyproject.toml 后,需要通过后续项目命令更新解析和同步结果;不要误解成文件一保存就有后台进程立即安装依赖。官方项目指南说明了这套项目流程。
编者补充:requests==2.31.0 是旧版本示例,本文没有对其当前漏洞状态进行扫描,不建议直接作为新项目的版本选择。Git URL 未显式指定提交时,项目最初取得的内容可能随分支变化;需要复现的构建应审核来源并采用经过确认的不可变提交或发布版本。uv sync 会使环境与项目要求同步,可能删除不属于所需依赖集合的额外包,因此不应拿混杂手动安装内容的环境来试验。
运行项目而不手工激活 shell
原文以 Flask 演示安装和运行入口:
uv add flask
uv run -- flask run -p 3000
它假设项目中已经有 Flask 能识别的应用;仅安装 Flask 并不会自动生成一个完整 Web 应用。开发服务器也不是生产部署方案。普通 Python 文件可以直接通过 uv run main.py 执行,例如原文的 main.py:
import flask
print("hello world")
术语修正:原文用“自动激活虚拟环境”来描述体验,更准确地说,uv run 在项目环境中启动目标进程,而不会替你激活当前交互式 shell。若其他工具仍需要传统激活方式,可以在 Unix shell 中执行:
uv sync
source .venv/bin/activate
python main.py
单文件脚本:用 PEP 723 声明依赖
只为一个脚本建立完整项目有时显得过重。PEP 723 定义了内联脚本元数据,用特殊注释块记录脚本需要的依赖。原文示例读取公开的 PEP JSON 接口:
# /// script
# dependencies = [
# "httpx",
# ]
# ///
import httpx
resp = httpx.get("https://peps.python.org/api/peps.json")
data = resp.json()
print([(k, v["title"]) for k, v in data.items()][:10])
把代码保存为脚本后,可以用 uv run example.py 运行。uv 会为声明了内联依赖的脚本准备隔离环境,原文提到 Unix 下默认缓存位置为 ~/.cache/uv。也可以让 uv 修改脚本的依赖声明:
uv add --script example.py 'requests<3' 'rich'
静态审查:原例的 URL 是固定公开地址,没有硬编码凭据,也没有把响应交给 eval。不过它没有检查 HTTP 状态便直接解析 JSON,依赖和响应结构也没有固定。本稿建议在 data = resp.json() 前增加 resp.raise_for_status(),以便 HTTP 错误尽早显现;这是一处明确的编者建议,并非已实测修复。真正用于自动化流程时,还应定义失败处理并按需要锁定脚本依赖。
在支持 env -S 的 Unix 环境,可以用 shebang 让一个有执行权限的脚本直接由 uv 启动:
#!/usr/bin/env -S uv run --script
print("Hello, world!")
如果文件名为 greet,且已经具备执行权限,便可以运行 ./greet。原文将这一方式称作“打包成可执行文件”;严格说,它仍然是脚本,需要系统能找到 uv,并不是无需依赖的独立二进制程序。
命令行工具:与项目依赖分开
许多 Python 包同时提供命令行程序。uv 为这类工具提供独立入口:
uv tool run ruff
# uvx 是 uv tool run 的别名:
uvx ruff
工具在独立于项目的环境里运行,减少工具依赖与项目依赖的冲突。经常需要的命令也可以使用 uv tool install ruff 持久安装,再通过 PATH 调用;不再使用时由 uv tool uninstall ruff 移除。原文提到的 ~/.local/bin 是常见 Unix 命令入口目录,不是跨平台的固定路径。
工具安装不会自动把模块放进当前项目的 Python 环境。仅仅做过 uv tool install ruff,不能据此假定另一个解释器中的 python -c "import ruff" 会成功。如果当前环境本来已有同名包,结果又可能不同;关键是理解两种环境互相隔离。
这种隔离解决的是依赖冲突,不等于安全沙箱。脚本、工具与包的构建过程仍然可能执行代码并使用当前用户权限;审查陌生项目时,不能因为通过 uv 启动就放任它接触凭据、个人文件或生产目标。
把统一入口用在合适的边界上
原文看重的是一个工具覆盖解释器、项目、独立脚本与命令行工具的便利。迁移时最值得保留的是这几条边界:用版本文件选择解释器,用项目声明与锁文件维护依赖,用项目环境运行应用,用脚本元数据描述单文件需求,把工具放到自己的环境。迁移完成后仍要在目标平台验证项目输出、锁文件和运行方式;本文没有执行安装器、安装任何包,也没有运行源文脚本。
原文扩展阅读:uv is the best thing to happen to the Python ecosystem in a decade — Dr. Emily L. Hunt。












暂无评论内容