UV
Quick reference for UV package manager commands
Using uv as Python Package Manager
Python has a long history of package managers, each generation having its own strengths and more importntly, weaknesses. As of 2025, uv is aiming to be the best tool on the market and generally it is. Astral focused on speed which never was a major concern for Python package managers before, but after using uv, going back to pip or poetry feels like a clear downgrade.
uv is available for all major platforms (Linux, macOS). It self-contained, meaning it does not require Python to be pre-installed, it can manage Python distributions itself, downloading and installing specific versions as needed.
# macOS
brew install uv
# Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Docker
COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
Bootstrapping a Python Project with uv
Use uv init --package for new projects. This creates a src layout which separates source code from project root, preventing import conflicts and ensuring installed package matches development structure.
uv init --package
uv venv --python 3.13
Generated structure:
pyproject.toml- project metadata and dependenciessrc/<project>/- package directory with__init__.py.python-version- pins Python version.venv/- virtual environment
Pin Python to a specific minor version. Prevents unexpected breakage from minor version upgrades across environments.
requires-python = ">=3.13,<3.14"
Use uv add for dependency management. Tracks dependencies in pyproject.toml and updates lockfile automatically. Prefer over uv pip install for project dependencies.
uv add pandas openpyxl # runtime dependencies
uv add --dev ruff pytest # dev dependencies
Use GitHub’s official Python .gitignore. Community-maintained and comprehensive. Covers modern tooling out of the box.
curl -sL https://raw.githubusercontent.com/github/gitignore/refs/heads/main/Python.gitignore -o .gitignore
See Makefile for standard make test, make lint, make fmt targets.
Use Hatchling as the build backend with dynamic versioning. See CalVer for version format.
Hatchling Build Backend
Use hatchling as the build backend. Modern, fast, and supports dynamic versioning out of the box.
# pyproject.toml
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Dynamic Version with Hatchling
Use hatchling for single-source versioning. Define version in __init__.py and let hatchling read it automatically.
# src/<package>/__init__.py
__version__ = "2026.2.0"
# pyproject.toml
[project]
dynamic = ["version"]
[tool.hatch.version]
path = "src/<package>/__init__.py"
This enables from package import __version__ at runtime while keeping version in one place.
CalVer Date-based Versioning
Use CalVer YYYY.MM.MICRO for date-based releases. Month is short format (1, 2, … 12), not zero-padded.
| Format | Example | Meaning |
|---|---|---|
YYYY.MM.MICRO | 2026.2.0 | Preferred - short month |
YYYY.0M.MICRO | 2026.02.0 | Avoid - zero-padded month |
MICRO increments for patches within a month. Resets to 0 on new month. Reference: calver.org
Using uv for Managing Python Virtual Environments
uv can create and manage virtual environments. It handles dependency resolution, installation, and environment setup.
# Create .venv (replaces python -m venv .venv)
uv venv
uv venv --python 3.12
# Install package (replaces pip install <package>)
uv pip install requests
# Run command within venv (replaces source .venv/bin/activate && python main.py)
uv run python main.py
uv run pytest
uv has several notable environment variables to control its behavior:
UV_PYTHON_PREFERENCE=only-system # Use only system Python (useful in Docker)