Uv is fantastic, but its package management UX is a mess
Python developers weigh the trade-offs of using uv, a fast, all-in-one package and environment manager whose command-line UX and default behaviors some find confusing or risky. A central tension is uv’s choice not to add upper version bounds by default and to separate “lockfile upgrade” from “requirement upgrade,” which critics say can lead to unexpected breaking changes while defenders argue it avoids unsolvable dependency trees and aligns with Python’s ecosystem realities. Despite these usability complaints, many contributors still view uv as a major improvement over pip, Poetry, and Conda, particularly for speed, dependency resolution, and making virtual environment management largely disappear.
Overall sentiment
- Many see uv as a major improvement for Python packaging: fast, reliable resolution, good env management, “best thing that’s happened to Python in a long time.”
- Others think the article’s “UX is a mess” framing is too strong / click‑driven, but still agree there are real usability issues.
- A minority say they don’t feel much benefit over existing tools (pip, poetry, conda) for their workflows and are wary of fanboyism.
CLI & UX criticisms
- Command layout feels designed for correctness and machines, not humans: key actions split across
uv,uv lock, anduv pip, with surprising defaults. - Examples:
uv lock --upgradeupgrades everything, including majors, which users find risky; there’s no obvious “safe, semver‑bounded update” path.- Two different “outdated” views (
uv pip list --outdatedvsuv tree --outdated) with inconsistent UX. - Useful commands (e.g.,
uv pip show) feel “hidden” and miss information compared to pip.
- Some users work around this with command runners, aliases, or by editing
pyproject.tomldirectly.
Version bounds, semver, and upgrades
- Big debate over upper bounds:
- Pro‑bounds (especially for apps): want protection from breaking majors; see boundless updates as unsafe.
- Anti‑bounds (especially for libraries): upper bounds frequently cause unsatisfiable trees; Python packages often don’t follow semver anyway.
- Uv deliberately avoids upper bounds by default; flags and config exist to change this, but discoverability is poor.
- Many prefer exact pins via lockfiles and use bots (Dependabot/Renovate) plus
uv tree --outdatedrather than relying on version ranges.
Dependency resolution & performance
- Uv’s resolver is widely praised: resolves trees pip/poetry struggle with, much faster, benefits from caching and parallel downloads.
- Some debate how much speed comes from Rust vs newer packaging standards vs dropping legacy features; even a uv maintainer disputes the “it’s just dropped features” narrative.
Workflows & ecosystem fit
- Some only use uv for env creation, then stick with pip/requirements.txt.
- Others lean on
uv tool/uv runbut report friction around auto‑upgrading shared scripts. - Python’s inability to load multiple versions of a package in one process underlies many constraints; import‑hook hacks are discussed but seen as brittle.
Scientific & ML packaging
- Uv doesn’t fix deep issues around heavy compiled deps (PyTorch, CUDA, long‑tail scientific packages).
- Scientific maintainers note progress (e.g., moving away from Fortran, more C wheels), but acknowledge this area remains painful.