- What problem uv solves
- Python environments and isolation
- Installing and using uv
- Creating a project
- Dependency management
- Running code and scripts
- Lockfiles and reproducibility
- Project structure and hygiene
- Tooling integrations
- Best practices and common mistakes
- Migration and comparison with older tools
- Why Python projects break
- “Works on my machine” explained
- Dependencies, versions, conflicts
- Why pip alone is not enough
Motivation and explanation of the problem space before starting.
We need to feel the pain first to justify the workflow uv solves.
- very lighy intro of historioc tooling,
pip,venv.,poetryandpipenvpluspyenv. - emphasize that
uvreplaces most of these tools, not adds more tooling on top.
- Global Python vs project Python
- What a virtual environment is
- Why isolation matters
- One project, one environment
uv concepts make no sense without environments.
This section builds the mental model uv relies on.
PATH, PYTHONPATH, system python changes without notice,
packaging python dependencies also makes them old.
Multiple Python versions existing at once.
- Installing uv on macOS, Linux, Windows
- Verifying installation
uv --help- Philosophy of
uvcommands
Get them started on a basic project. Quick trial, "Hello Python".
- Why
uvis fast: Rust plus local cache. - Single binary concept
https://github.com/isotopp/uv-class/tree/main/berlin-weather
- uv init
- Project layout overview
pyproject.tomlpurpose- Naming a project
- With the example project, now go through things in detail
- What
pyproject.tomlreplaced
uv adduv remove- Runtime vs development dependencies
- Semantic versioning basics
This is the core daily use of uv.
Students should learn safe dependency habits early.
- What dependency resolution means
- Why pinning matters
uv run- Running Python files
- Entry points
- Scripts vs modules
- Reproducible execution
- Brief mention of shebangs (if needed)
- What a lockfile is (what does
uv.locklook like exactly, and why is that there?) - What is actually used when
uv syncanduv runare used -pyproject.tomloruv.lockand why? - Sharing projects and deterministic installs
- The
uv lockcommand and upgrades.
- Why lockfiles belong in git
srclayout vs flat layout- Keeping tests separate
- README basics
- Ignoring files correctly
- Minimal
.gitignore - Naming conventions
- Linters and formatters via
uv - Testing tools
- Running tools consistently
- Shows
uvas a hub, not just a dependency installer. - Encourages automation thinking.
ruffas an examplepytestbasics
uvvspip+venvuvvspoetry- When
uvis enough - When something else might be needed
Core idea: Building a Python project means turning source code into a distributable artifact.
That artifact is usually:
- a wheel (.whl)
- sometimes a source distribution (.tar.gz)
Building does not mean:
- running the code
- installing dependencies
- compiling Python itself
Building is packaging code so someone else can install it without your source tree.
- What a build artifact is
- When building is required
- What uv does and does not do
- Relationship between build and install
Examples:
- internal tools
- applications run from source
- services deployed from a git checkout
- projects using
uv run
Most application developers never need to build wheels.
Examples:
- publishing a library
- distributing a CLI to users
- shipping prebuilt artifacts
- CI/CD release workflows
- uv understands build metadata
- uv installs build dependencies
- uv delegates building to a backend
uv is an orchestrator, not a compiler.
- Difference between “editable install” and built wheel
- Why wheels are preferred over source installs
Core idea: A wheel is a pre-packaged, installable Python package distribution.
Properties:
- fast to install
- no code execution during install
- deterministic contents
- platform-specific when needed
berlin_weather-0.1.0-py3-none-any.whl
- Wheel naming
- Platform tags
- Pure Python vs platform wheels
- Why wheels exist
Most python people do not even know what a wheel is and why it matters.
- metadata
- packaged modules
- entry points
- py3-none-any
- easiest case
- common for teaching examples
- OS and architecture tags
- C extensions
- why building becomes harder
- why source distributions still exist
- why wheels are cached aggressively
Core idea: A build backend is the tool that actually performs the build of a wheel.
Examples:
- setuptools (strongly deprecated)
- hatchling (previously the default in
uv) - poetry-core
- uv_build (now default in
uv)
Defined in pyproject.toml:
[build-system]
build-backend = "uv_build" # The default- PEP 517 and PEP 518
- Role of
[build-system] - Separation of frontend and backend
- Why backends exist
uvdoes not build, it uses a backend- the backend is pluggable
- tooling interoperability depends on this design
- Frontend: uv, pip, build
- Backend: hatchling, uv_build
The frontend asks for a build, the backend performs it.
- no arbitrary code execution
- reproducible builds
- isolated build environments
- Why most users never touch
[build-system] - When changing backends makes sense
Core idea: Publishing means uploading built artifacts to a package index ("index").
Common targets:
- PyPI
- internal company registries (actualy just an Apache dir, but many shops use JFrog Artifactory)
- private indexes or caches
Publishing always comes after building.
- Build vs publish
- Versioning responsibility
- Authentication and trust
- Release automation
- libraries
- reusable tools
- shared components
In companies, teams usually publish to artifactory, so that production, CI and other teams pull from there.
- internal scripts
- applications deployed from source
- coursework projects
- uv prepares metadata
- uv installs build tools
- upload handled by dedicated tooling
- uv integrates, it does not monopolize.
- Why publishing is a social contract
- Why version numbers matter
- Why deletion is discouraged