Astral的uv已经席卷了Python世界,理由很充分:它速度极快,轻松处理Python版本,用一个二进制文件替代了半打工具。但是,当你从初始设置进入项目的维护阶段——检查过时包和进行例行升级——CLI开始感觉出奇地笨拙。
查找过时包的痛苦
在JavaScript项目中,如果你想看看什么需要更新,运行:
$ pnpm outdated
这会给你一个干净、简洁的列表,显示过时的包、当前版本、最新版本,以及你的约束允许的版本。
在uv中,没有uv outdated命令。相反,你必须记住这个冗长的命令:
$ uv tree --outdated --depth 1
输出也有问题。它不仅显示过时的包,还显示你整个顶级依赖树,只有一个小注释标注哪些有更新可用。如果你有50个依赖,只有两个过时,你仍然需要扫描50行列表。
默认的不安全版本约束
这是uv与pnpm和Poetry最重大的哲学分歧,对生产稳定性来说是危险的。
pnpm/Poetry的做法
当你使用pnpm add添加包时,它写入package.json使用插入号要求(^1.23.4)。开头的插入号意味着允许任何1.x.x版本,但不会更新到2.0.0。Poetry默认做同样的事情。
在这两种情况下,更新默认是安全的。你可以每天早上运行pnpm update或poetry update,高度自信你的构建不会因为重大API变更而中断。
uv的做法
当你运行uv add pydantic时,它在你的pyproject.toml中插入:
dependencies = [
"pydantic>=2.13.4",
]
注意没有上限。在uv看来,pydantic版本2、3和100都是完全可以接受的。这意味着uv更新默认是不安全的。
如果你运行批量更新,你不仅得到错误修复;你正在接受每个维护者发布的每个破坏性变更。
升级命令的糟糕UX
uv中实际执行更新的命令感觉是为机器而不是人类设计的。
如果你想在pnpm或Poetry中更新所有内容,只需简单的pnpm update或poetry update命令。
在uv中,你使用:
$ uv lock --upgrade
为什么这不是简单的uv update或uv upgrade?谁设计了这个命令行界面?
由于上面提到的”无上限”问题,uv lock --upgrade是一个核武器选项。它会将你lockfile中的每个包升级到绝对最新版本,忽略语义版本安全。这包括你从未听说过的深层嵌套依赖!
对Python开发者的建议
1. 手动指定版本上限:使用uv时,建议手动添加版本上限,如>=2.13.4,<3.0.0
2. 使用uv lock --upgrade-package:只升级特定包,而不是全部
3. 定期检查依赖:使用uv tree --outdated --depth 1定期检查
4. 考虑使用poetry:如果你更看重安全性和UX,Poetry可能是更好的选择
总结
uv的速度确实令人印象深刻,但包管理的UX需要改进。对于生产环境,建议谨慎使用uv的更新功能,或者考虑使用Poetry作为替代方案。
本文参考来源:uv is fantastic, but its package management UX is a mess















暂无评论内容