uv venv — 极速创建虚拟环境
即使你不想用完整的项目模式(uv init),uv 也可以纯粹当一个"超快的 venv 工具"用:
# 默认创建到 .venv
uv venv
# 指定路径
uv venv myenv
uv venv ~/.virtualenvs/playground
# 指定 Python 版本(自动下载)
uv venv --python 3.13
uv venv --python 3.12.4
# 不基于项目的 pyproject,自定义 requires
uv venv --python 3.13 --prompt mycli
# shell 激活后提示符显示 (mycli)
性能对比:
| 工具 | 创建空 venv 耗时 |
|---|---|
python -m venv | ~1.2s |
virtualenv | ~0.6s |
uv venv | ~0.015s |
venv 里有什么?
.venv/
├── bin/ # Linux/macOS;Windows 是 Scripts/
│ ├── activate # 传统激活脚本(bash)
│ ├── activate.fish
│ ├── python3 # 软链到实际 Python 解释器
│ └── pip # 虽然 uv 不用 pip,它仍被安装
├── lib/python3.13/site-packages/ # 装的包在这里
└── pyvenv.cfg # 记录 Python 路径、venv 类型
激活 vs 免激活
传统工作流:
source .venv/bin/activate # 激活
python main.py # 用 venv 里的 python
deactivate # 用完记得退出
uv 工作流(推荐):
uv run python main.py # 直接跑,不激活
uv run pytest # 跑 venv 里的 pytest
uv run -- ruff check . # -- 后面是原命令(避免 ruff 的参数被 uv 解释)
① 零记忆负担:不会忘记是否激活了正确环境。② 跨项目安全:在项目 A 的 shell 里敲 uv run 自动用 A 的 venv,即使你刚从项目 B 的激活环境切过来。③ IDE 友好:VS Code 的 Python 扩展本就能自动识别 .venv,无需激活。
uv run 的魔法
uv run 在执行命令前会自动:
- 查找项目根(向上找 pyproject.toml)。
- 确保所需 Python 版本已安装(没装会下载)。
- 确保
.venv存在且与uv.lock一致(不一致会自动 sync)。 - 激活该 venv 的 PATH 和环境变量。
- 执行你的命令。
# 常用用法
uv run python script.py
uv run pytest tests/
uv run jupyter lab
uv run uvicorn app:main --reload
# 不自动 sync(提高启动速度,假设环境已对)
uv run --no-sync python main.py
# 以特定组的依赖运行
uv run --group docs mkdocs serve
uv run --all-extras pytest
# 传环境变量
uv run --env-file .env python main.py
uv run DEBUG=1 python main.py # 行内变量
PEP 723 — 单文件脚本的依赖
经常有这样的场景:你想写一个 60 行的小工具脚本依赖 requests 和 click,但不想创建完整项目。传统做法是全局装依赖污染系统,或者搞个 venv 显得小题大做。
PEP 723 允许把依赖写在脚本开头的特殊注释里:
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "httpx",
# "rich",
# ]
# ///
import httpx
from rich import print
r = httpx.get("https://api.github.com")
print(r.json())
# uv 会自动解析这段元数据,创建临时 venv,装依赖,跑脚本
uv run my_script.py
# 生成这段注释骨架
uv init --script my_script.py
# 给脚本添加依赖(自动更新注释)
uv add --script my_script.py rich httpx
# 指定 Python 版本
uv run --python 3.13 my_script.py
① 运维脚本:部署、备份、数据迁移的一次性工具。② CLI 小工具:想分享给同事的"chmod +x 直接跑"脚本。③ 教学示例:博客和 README 里贴代码,读者一条 uv run 即可复现。
shebang — 让脚本可直接执行
#!/usr/bin/env -S uv run --script
# /// script
# dependencies = ["rich"]
# ///
from rich import print
print("[bold cyan]Hello from a portable Python tool![/]")
chmod +x hello.py
./hello.py # 直接跑,uv 自动处理依赖
环境变量与 dotenv
uv 原生支持 .env 文件(需要 --env-file):
# .env
DATABASE_URL=postgres://localhost/mydb
OPENAI_API_KEY=sk-...
# 运行时加载
uv run --env-file .env python main.py
# 或在 pyproject 里永久配置
[tool.uv]
env-file = ".env"
venv 的迁移性
.venv 里的 Python 解释器是软链到你机器上某个绝对路径的,直接打包发给别人不能用。正确做法:把 pyproject.toml + uv.lock + .python-version 提交到 git,别人 uv sync 即可获得一模一样的环境。
uv pip — pip 兼容接口
某些老教程、老 CI 脚本只会 pip install xxx。uv 提供了一个完全兼容 pip 命令行的子命令:
uv pip install requests
uv pip install -r requirements.txt
uv pip list
uv pip freeze
uv pip uninstall requests
uv pip compile requirements.in -o requirements.txt # pip-tools 替代
注意:uv pip 是兼容层,不会动 pyproject.toml 和 uv.lock。在项目模式里永远用 uv add;uv pip 只在非项目场景(快速试用某包、兼容遗留脚本)使用。
uv venv 创建环境比 venv 快 80 倍,uv run 让"激活"成为历史,PEP 723 让单文件脚本也能管依赖。养成习惯:任何 Python 命令都用 uv run ... 开头,从此跨项目切换零心智负担。下一章讲 uv tool——全局安装 CLI 工具的现代方式。