# uv Solved the Packaging UX, Not Packaging


Someone asked me what the new [Python Packaging Council](https://pydevtools.com/handbook/explanation/what-is-pep-772.md) could possibly work on "now that uv has largely standardized packaging." [uv](https://pydevtools.com/handbook/reference/uv.md) has made installing packages, managing environments, and resolving dependencies fast enough that packaging feels solved. That assumption mistakes one layer of the stack for the whole thing.

uv addressed the developer workflow: fast installs, fast resolution, a single CLI that replaces [pip](https://pydevtools.com/handbook/reference/pip.md), [pip-tools](https://pydevtools.com/handbook/reference/pip-tools.md), [pyenv](https://pydevtools.com/handbook/reference/pyenv.md), [pipx](https://pydevtools.com/handbook/reference/pipx.md), and [virtualenv](https://pydevtools.com/handbook/reference/virtualenv.md). That layer matters, and uv did it well. But the hardest unsolved problems sit in layers uv consumes rather than controls.

## What uv actually settled

uv collapsed several tools into one fast binary. Resolution that took minutes takes seconds. Virtual environments, scripts, Python versions, and CLI tools all route through a single interface. For a pure-Python project with [PyPI](https://pydevtools.com/handbook/explanation/what-is-pypi.md) dependencies, the workflow feels finished.

uv also has a [build backend](https://pydevtools.com/blog/uv-build-backend.md) now, constructing wheels and source distributions without invoking Python. But it only supports pure Python packages and has no build script support, so projects that need compiled extensions (C, Cython, Fortran, Rust) or custom build-time logic (code generation, asset compilation) still reach for [setuptools](https://pydevtools.com/handbook/reference/setuptools.md), hatchling, maturin, scikit-build-core, or meson-python. uv consumes the [PEP 517](https://pydevtools.com/handbook/explanation/what-is-pep-517.md) build interface; it doesn't replace the ecosystem of backends behind it.

## Wheels can't describe modern hardware

The [wheel format](https://pydevtools.com/handbook/reference/wheel.md) carries three compatibility tags: Python version, ABI, and platform. None of them describe CPU microarchitecture or GPU. A NumPy wheel targeting `manylinux_2_17_x86_64` must run on every x86-64 CPU shipped since the early 2000s, leaving [10x to 20x performance on the table](https://talkpython.fm/episodes/show/544/wheel-next-packaging-peps) for workloads that could use AVX2 or AVX-512.

GPU packages are worse. PyTorch ships separate builds for CUDA 12.6, 12.8, 13.0, and CPU-only, but has [no standard way to publish them all to PyPI](https://pydevtools.com/handbook/explanation/installing-cuda-python-packages.md) and let an installer choose. Every CUDA-dependent project invents its own workaround: custom index URLs and mangled package names like `cudf-cu12`.

The [wheel variants proposal](https://pydevtools.com/handbook/explanation/what-are-wheel-variants.md) ([PEP 817](https://peps.python.org/pep-0817/) and [PEP 825](https://peps.python.org/pep-0825/)) would extend wheel metadata so packages can ship hardware-specific builds and let the installer pick the right one. uv has experimental support, but the standard needs to be accepted and stabilized. That requires the Packaging Council to evaluate the proposals and coordinate across tools.

## Python can't declare non-Python dependencies

A package that wraps OpenSSL, links against libcurl, or needs a Fortran compiler has no standard way to say so in `pyproject.toml`. That information lives in READMEs and StackOverflow answers. When the install fails, the error is a C compiler traceback that says nothing about what system package is missing.

[PEP 725](https://peps.python.org/pep-0725/) proposes an `[external]` table in `pyproject.toml` for declaring these dependencies, using a URL format that maps across package managers (apt, brew, conda). It's been in draft since 2023, with a long Discuss thread and no resolution. The technical design is genuinely hard (mapping across distros, choosing a URL format), and the lack of an authoritative body to make binding decisions hasn't helped.

## Lockfiles have a standard the ecosystem hasn't adopted

[PEP 751](https://pydevtools.com/handbook/explanation/what-is-pep-751.md) gave Python a standard lockfile format (`pylock.toml`), accepted in March 2025. pip has experimental support; uv has its own `uv.lock` that predates the standard. The standard exists, but the ecosystem hasn't converged on it. Cross-platform semantics, transition-period guidance, and inevitable revisions as adoption surfaces edge cases all need shepherding.

## PyPI carries the ecosystem on a small team

[PyPI](https://pydevtools.com/handbook/explanation/what-is-pypi.md) serves over a billion downloads per day, maintained by a small PSF team. Typosquatting, rate limits that conflict with monorepo publishing, and an [upload API](https://peps.python.org/pep-0694/) overdue for modernization are all active problems. None of that is in uv's scope.

## Test dependencies lack a cross-tool standard

Every packaging tool declares test dependencies differently. [Poetry](https://pydevtools.com/handbook/reference/poetry.md) uses dependency groups, uv uses `[dependency-groups]` per [PEP 735](https://pydevtools.com/handbook/explanation/what-is-pep-735.md), and plenty of projects still use `requirements-dev.txt`. A standard has been debated on Discuss without consensus, the kind of cross-tool coordination that speed alone won't resolve.

## Governance was the bottleneck

These problems stalled not because nobody proposed solutions, but because nobody had authority to decide. Packaging PEPs relied on [individual standing delegations from the Steering Council](https://pydevtools.com/handbook/explanation/why-doesnt-python-just-fix-packaging.md), and the Steering Council acknowledged that [packaging governance requires different expertise](https://pydevtools.com/blog/why-isnt-python-packaging-part-of-core-development.md) than language governance. When delegates were unavailable or a proposal touched multiple tools, progress slowed to a crawl.

[PEP 772](https://pydevtools.com/handbook/explanation/what-is-pep-772.md) created the Packaging Council to fix this: five elected members with authority over packaging standards, accountable through PSF elections. The council exists to evaluate proposals like PEP 725 and wheel variants, make binding decisions, and coordinate across uv, pip, Poetry, and whatever comes next.

## Faster resolvers won't fix standards problems

uv made the packaging experience feel solved for the most common case: a pure-Python project with PyPI dependencies on a standard platform. That changed what people expect from Python tooling. But hardware-specific distribution, system dependency declaration, lockfile convergence, and registry security all require standards bodies, not faster resolvers.

The Packaging Council has plenty of work ahead.

## Learn More

- [What is PEP 772?](https://pydevtools.com/handbook/explanation/what-is-pep-772.md)
- [Why doesn't Python just fix packaging?](https://pydevtools.com/handbook/explanation/why-doesnt-python-just-fix-packaging.md)
- [What are wheel variants?](https://pydevtools.com/handbook/explanation/what-are-wheel-variants.md)
- [Why Installing GPU Python Packages Is So Complicated](https://pydevtools.com/handbook/explanation/installing-cuda-python-packages.md)
- [What is PEP 751?](https://pydevtools.com/handbook/explanation/what-is-pep-751.md)
- [PEP 725: Specifying external dependencies in pyproject.toml](https://peps.python.org/pep-0725/)
- [PEP 772: Packaging Council governance process](https://peps.python.org/pep-0772/)
