✎ Edit content·DAY 023 · POST 4 OF 5 · Code Example

Virtual Environments & uv

Python · 11 slides
DAY 023 · POST 4 OF 5
(REMINDER)
DAY 023
uv: A Full Walkthrough
@saurav_dnj_24github.com/SauravDnj · linkedin.com/in/sauravdnj
1 / 11

Theme

Palette

Download

4K — sharpest, slowest
🎬 Video options
Preparing preview…
Live preview · loops the “none” effect
All rendering runs in your browser. No server, no cost, no upload. MP4/WebM = full motion + effects · GIF = lightweight loop · PNG/PDF = static for the Instagram & LinkedIn carousel.

Caption (tap to copy)

📖 Deep dive (full written explanation)

The slides stay clean and scannable. Here's the in-depth explanation behind each one — great for the blog version, show notes, or studying the topic properly.
Slide 1 · uv: A Full Walkthrough

This cover signals a shift from explanation to execution. The previous posts built the model; this one is a copyable recipe. We take a project from an empty folder to a locked, reproducible application using only uv, with every command real and runnable.

The goal is muscle memory. By the end you should be able to start any new Python project with a handful of uv commands without looking them up, which is the point at which good environment hygiene becomes effortless rather than aspirational.

Slide 2 · 1. Start a project

'uv init weather-app' scaffolds a new project directory with sensible defaults. It generates a pyproject.toml holding your project's metadata and (soon) its dependencies, a .python-version file pinning which interpreter the project expects, a starter main.py, and a README.md.

This single command replaces the usual scramble of creating files by hand and remembering the right pyproject.toml boilerplate. Starting from 'uv init' means your project is correctly structured for locking and syncing from the very first commit, rather than being retrofitted later.

Slide 3 · 2. Add dependencies

'uv add' is the workhorse you'll use constantly. 'uv add requests rich' installs those runtime packages, and on the first add it transparently creates the .venv if one doesn't exist. Critically, uv add does three things at once: it resolves and installs, it records the dependency in pyproject.toml, and it updates uv.lock with the exact pinned versions.

The '--dev' flag adds a dependency to a separate development group instead of the runtime dependencies. 'uv add --dev pytest ruff' records your test runner and linter as tools needed for development but not for production. This single-command flow — install, declare, and lock together — is what keeps your manifest and your environment from ever drifting apart.

Slide 4 · 3. What pyproject.toml holds

This slide shows the pyproject.toml that the previous commands produced. The [project] table holds the name, version, and a 'requires-python' constraint declaring the minimum interpreter. The 'dependencies' list contains your runtime packages with version constraints uv chose.

The [dependency-groups] table holds the 'dev' group with pytest and ruff. The separation is meaningful: a production install can pull only the runtime dependencies, while developers install everything. Note that these constraints are ranges (>=), expressing intent; the exact versions that get installed are pinned separately in uv.lock.

Slide 5 · 4. Write and run the app

This is the actual application, kept deliberately small so the focus stays on the workflow. It imports requests and rich, makes a GET request to the GitHub API, and prints a colorized status line. The libraries are the two runtime dependencies we added earlier, proving they're available in the environment.

The key line is the comment at the bottom: 'uv run python main.py'. You don't activate anything. uv run ensures the environment is synced and then executes the script inside it. This is the idiomatic way to run code in a uv project.

Slide 6 · Runtime vs dev deps

This slide explains the runtime-versus-dev distinction that the '--dev' flag encodes. Runtime dependencies — here requests and rich — are what the application genuinely needs in order to function in production. Development dependencies — pytest and ruff — are tools used only while building and testing the code.

Keeping them separate has real consequences. A production deploy installs the lean runtime set, reducing image size and attack surface, while developers get the full toolkit. 'uv add --dev' is how you tell uv which side of that line a package belongs on, and it's worth being deliberate about it from the start.

Slide 7 · The uv command flow

This pipeline summarizes the four commands that form the spine of the uv workflow: 'uv init' to scaffold, 'uv add' to install dependencies while updating the lock, 'uv lock' to pin exact versions, and 'uv run' to execute code inside the environment.

Seeing them in sequence reinforces the natural order of a project's life. You init once, add repeatedly as the project grows, lock whenever you change dependencies, and run constantly. Almost everything you do day to day is some combination of these four verbs.

Slide 8 · 5. Lock, sync, and clean up

This slide rounds out the lifecycle with maintenance commands. 'uv lock' re-resolves your declared constraints and refreshes uv.lock — useful when you want to deliberately pull in newer compatible versions. 'uv sync' rebuilds the .venv to match the lockfile exactly, the command teammates and CI run after a checkout. 'uv remove rich' deletes a dependency from both the manifest and the lock. 'uv run pytest' executes your test suite inside the environment.

Together these cover the routine churn of a real project: adding, removing, relocking, and resyncing as requirements evolve, all while keeping the declared and actual states aligned.

Slide 9 · What to commit to git

Knowing what to commit is as important as the commands. You commit pyproject.toml (your declared intent), uv.lock (the exact resolved versions), and .python-version (the pinned interpreter). Together these three files fully describe the environment in a portable way.

You explicitly do NOT commit the .venv folder. It's large, machine-specific, contains absolute paths that break on other systems, and is entirely rebuildable from the three committed files via 'uv sync'. Treating .venv as a disposable build artifact rather than source is a habit that keeps repos clean and portable.

Slide 10 · The commands you'll use daily

These bullets distill the post into the commands you'll actually reach for daily: 'uv init' to start, 'uv add' and 'uv remove' to manage dependencies, 'uv sync' to rebuild from the lock, 'uv run' to execute in the environment, and 'uv lock' to refresh the pins.

If you pin this list somewhere until it's automatic, you have everything needed to manage real projects. The surface area of uv for everyday work is genuinely small, which is part of its appeal — five verbs cover the overwhelming majority of what you do.

Slide 11 · Save this. Follow for Day 24.

This closes the hands-on post and previews the final angle. You can now drive a project end to end with uv. The last post catalogs the common mistakes — the invisible env traps that quietly cost hours — so you can recognize and avoid them before they bite.

🎨 AI image prompt (matches this theme + palette)

Paste into Midjourney, DALL·E, Ideogram, etc. to generate an on-brand image, then upload it on the Edit content page. The prompt updates automatically with the selected theme + palette.