Run one Python project end to end on uv — pinned interpreter, locked dependencies, reproducible commands, and dependency-carrying single-file scripts — and leave pip-forgetting behind.
- A Python project with a requirements file, pyproject.toml, or Poetry lock
- uv installed, or a willingness to install it with one command
- No project rewrite required
uv has become the default workflow for new Python projects: one Rust binary manages interpreters, virtual environments, dependencies, lockfiles, and project commands. For AI coding it matters even more — a single uv run gives your agent a reproducible environment without shell history archaeology.
You are done with this guide when uv run executes your checks on a pinned interpreter with a committed lockfile, and a clean clone reaches the same result.
Pin the interpreter first
uv python install 3.12
uv python pin 3.12
The pin lands in .python-version, so every contributor, CI runner, and coding agent resolves the same interpreter. This replaces per-machine Python guesses — the same discipline the free-threading decision guide relies on.
Manage dependencies with a real lockfile
uv init
uv add httpx pytest
uv lock
uv.lock records the full resolved graph, including transitive dependencies and hashes. Commit it. uv add and uv remove keep pyproject.toml and the lockfile in sync, which removes the two-files-drift failure mode of hand-edited requirements.
The uv documentation covers projects, workspaces, and tool management; the feature overview is the fastest map of what replaces which old command.
Run everything through uv
uv run pytest -q
uv run python -m mypackage.cli
uv run syncs the environment from the lockfile before executing, so “works on my machine” stops being a state you can reach by accident. This is also the exact property that makes AI-generated code trustworthy enough to run: the agent cannot silently depend on a package that is not declared.
Scripts that carry their own dependencies
Single-file scripts can declare dependencies inline, so they run anywhere without a project around them:
# /// script
# dependencies = ["httpx"]
# ///
import httpx
print(httpx.get("https://flypython.com/llms.txt").status_code)
Run it with uv run script.py — uv creates an ephemeral environment from the header block. Useful for automation one-offs you still want reproducible.
Migrate without a rewrite
- From pip + venv: delete the manual activation habit;
uv pip install -r requirements.txtonce, then move entries touv add. - From Poetry:
uv initin place,uv addyour dependencies frompyproject.toml, deletepoetry.lock, and commituv.lock. - From tox/Make glue: keep the tasks, but make every line start with
uv run.
Packaging and publishing follow the same standard — see the Python packaging user guide for what pyproject.toml must declare when you ship a package; uv build produces the artifacts from it.
Sources
The uv documentation covers projects, interpreters, lockfiles, and scripts; its feature overview provides the command-by-command replacement map; the Python packaging user guide defines the pyproject.toml publishing contract. All three are linked where they are used above.
Verification record
Editorial review against the uv documentation and the Python packaging user guide. Verified 2026-09-06.
About the author
Organizational byline for FlyPython guides, verification records, and corrections. Editorial standards and contact details →