Open this lesson in your favourite AI. It'll walk you through the why, explain the demo, and quiz you on the try-it list.
Two things every Python project needs to be reproducible: an exhaustive list of every package (including transitive deps), and a way to recreate the same environment on another machine in 6 months. pyproject.toml lists direct deps; the lockfile pins the full graph with hashes. Pre-uv this was painful (pip-tools, poetry.lock, Pipfile.lock — pick your flavor). uv unifies it: uv lock produces uv.lock, deterministic and fast. Plain requirements.txt (with hashes) still works and is fine for the simplest projects.
A lockfile is the difference between 'this probably works' and 'this will always work': it pins not just your direct dependencies but every transitive dependency — including the exact wheel URL and SHA-256 hash — so that uv sync on any machine in any future year recreates the exact same environment. pyproject.toml lists only direct deps with flexible version constraints; uv lock performs SAT-style dependency resolution over those constraints to produce uv.lock, which is what you actually install from. Committing uv.lock to version control means a fresh developer clone or CI job builds in seconds from the pre-resolved graph, with no network round-trips for resolution.
# pyproject.toml lists direct deps:
[project]
dependencies = ["fastapi>=0.110", "httpx>=0.27"]
# lock the full transitive graph:
$ uv lock
Resolved 23 packages in 145ms
$ cat uv.lock | head -20
version = 1
requires-python = ">=3.12"
[[package]]
name = "anyio"
version = "4.3.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "...", hash = "sha256:..." }
...
# install from the lockfile (deterministic):
$ uv sync # creates .venv/ and installs exactly what's in uv.lock
# legacy path with pip + hashes:
$ uv pip compile pyproject.toml -o requirements.txt --generate-hashes
$ uv pip install -r requirements.txtpython3 main.pyuv lock on a project with deps. Open uv.lock — it's a lot of TOML. That's the point: total reproducibility.uv sync. Note it recreated the env from the lockfile, not from pyproject.toml directly.uv pip compile pyproject.toml -o requirements.txt --generate-hashes and inspect.pyproject.toml and run uv lock again. Look at the diff in uv.lock — that's what you'd review in PRs.Use these three in order. Each builds on the one before.
In one paragraph, explain the difference between `pyproject.toml` deps and a lockfile — and why I'd commit both.
Walk me through what `uv lock` does: SAT-style resolution, version selection, hash generation. Why is this different from `pip install -r requirements.txt`?
On a multi-platform team (some Mac, some Linux, some ARM) some deps install different binary wheels per-platform. How does `uv.lock` handle this — markers, platform-specific entries, fallbacks?