uv 与 Python 项目环境¶
uv 可以统一管理 Python 版本、项目依赖、锁文件和命令执行。项目底层仍会创建隔离的 .venv,但日常不需要手工执行 python -m venv、source .venv/bin/activate 和 pip install;统一通过 uv 操作,可以减少系统 Python 被污染和不同机器依赖不一致的问题。
.python-version → 使用哪个 Python
pyproject.toml → 项目直接依赖与版本范围
uv.lock → 完整且精确的依赖解析结果
.venv/ → uv 自动维护的本地隔离环境
uv run → 在正确环境中执行命令
安装和确认¶
uv 能使用已有 Python,也可以安装受管理的 Python。生产或流水线应固定主版本和经过验证的补丁版本,不要让每次构建自动漂移到未知版本。
创建项目¶
运维脚本或数据处理项目可以使用不需要打包发布的结构:
mkdir ops-data-tools
cd ops-data-tools
uv init --no-package
uv python pin 3.12
uv add pandas openpyxl pyyaml requests
uv add --dev ruff pytest
uv run python main.py
典型目录:
ops-data-tools/
├── .python-version
├── pyproject.toml
├── uv.lock
├── main.py
├── src/
├── tests/
├── input/
└── output/
.venv/、输入中的敏感原始数据和输出结果通常不提交;pyproject.toml、.python-version 与 uv.lock 应提交,以便其他机器复现环境。
常用命令¶
| 目的 | 命令 | 结果 |
|---|---|---|
| 初始化当前目录 | uv init --no-package |
创建项目配置 |
| 固定 Python | uv python pin 3.12 |
写入 .python-version |
| 添加依赖 | uv add pandas |
更新 pyproject.toml、锁文件和环境 |
| 添加开发依赖 | uv add --dev pytest |
只用于测试/检查 |
| 删除依赖 | uv remove pandas |
同步更新依赖定义 |
| 同步环境 | uv sync |
按锁文件准备 .venv |
| 严格按锁文件同步 | uv sync --locked |
锁文件过期时失败,适合 CI |
| 执行脚本 | uv run python main.py |
自动确认环境已同步 |
| 查看依赖树 | uv tree |
排查间接依赖和版本来源 |
| 升级单个依赖 | uv lock --upgrade-package pandas |
尽量只更新指定包 |
不要在 uv 项目里继续随意使用裸 pip install,否则 .venv 中可能出现未记录在锁文件里的包,换机器后无法复现。
pyproject.toml 示例¶
[project]
name = "ops-data-tools"
version = "0.1.0"
requires-python = ">=3.12,<3.13"
dependencies = [
"openpyxl>=3.1,<4",
"pandas>=2.2,<3",
"pyyaml>=6,<7",
"requests>=2.32,<3",
]
[dependency-groups]
dev = [
"pytest>=8,<9",
"ruff>=0.12",
]
pyproject.toml 表达允许范围,uv.lock 保存解析出的精确版本。锁文件由 uv 维护,不手工编辑。
一次性运行工具¶
不想把工具加入项目依赖时,可以使用 uvx:
固定版本更适合可重复执行:
CI 和服务器运行¶
--locked 会在 pyproject.toml 与 uv.lock 不一致时失败,防止流水线自行更新依赖。无网络环境要提前准备 uv、Python 发行包、包缓存或内部 Python 镜像源。
定时任务使用完整路径和明确工作目录,不依赖交互式 shell 激活:
15 2 * * * cd /opt/ops-data-tools && /usr/local/bin/uv run --locked python main.py >> /var/log/ops-data-tools.log 2>&1
常见问题¶
| 现象 | 优先检查 |
|---|---|
uv run 使用了错误 Python |
.python-version、requires-python、uv python find |
| 本机能跑,CI 不能跑 | uv.lock 是否提交;系统库、CPU 架构和 Python 版本是否一致 |
| 依赖下载失败 | DNS、代理、证书、内部镜像源和 uv 缓存权限 |
| 添加包后锁文件变化很大 | 依赖约束是否过宽;使用单包升级并检查 uv tree |
直接运行 python 找不到包 |
使用 uv run python ...,无需手工激活环境 |