Introduction
If youâve felt Python packaging and tooling getting⌠faster lately, youâre not imagining it. A new, Rust-powered toolchainâuv for packaging and projects, Ruff for linting/formattingâplus PEP 723 inline script metadata is changing how we build and share Python code. The result? Projects that set up in seconds, single-file scripts that run with their own dependencies, and one linter/formatter to rule them all. In this guide, weâll explore the âwhy now,â show you copy-paste-ready examples, and walk through real-world workflows to modernize your stack today. (Primary keywords: Python tooling, uv, Ruff, PEP 723.)
Sources: uv docs & benchmarks, Ruff docs, PEP 723, Python 3.13 notes. (Astral Docs)
Why this trend matters right now
Python 3.13 shipped with foundation-level changes like an experimental JIT and an optional free-threaded build (no GIL) that set the stage for performance-minded tooling and future speed-ups. Meanwhile, the community has embraced Rust-implemented toolsânotably Ruff and uvâthat deliver 10-100Ă speed improvements over traditional equivalents in everyday dev loops (installing deps, linting, formatting). On top, PEP 723 lets you embed dependencies directly in a script, making self-contained, shareable utilities trivial. (Python documentation)
Iâve found that when teams adopt uv + Ruff + PEP 723, they reduce onboarding friction dramatically: a new laptop can clone, install, check, format, and run a project in minutes without yak-shaving.
Core Concept #1 â uv: the fast package & project manager
uv is a drop-in replacement for common pip, pip-tools, and virtualenv commands, written in Rust and tuned for speed. It manages Python installs, environments, dependency resolution, lockfiles, building, and even publishing. Expect installs and resolves that feel instant, especially with warm caches. (GitHub)
Quickstart (project workflow)
# 1) Install uv (macOS/Linux/Windows installers available)
curl -LsSf https://astral.sh/uv/install.sh | sh
# then ensure `uv` is on your PATH
# 2) Create a new project
uv init fast-api-demo
cd fast-api-demo
# 3) Add dependencies
uv add fastapi uvicorn
# 4) Run your app inside the project environment
uv run uvicorn app:app --reload
Pro tip: uv mirrors pip commands when you need them:
uv pip install -r requirements.txt
uv pip install -r pyproject.toml --extra dev
Core Concept #2 â PEP 723: self-contained scripts
PEP 723 defines inline script metadata so a single file can declare its dependencies. Tools like uv read that header, build a temporary env, install deps, and run the scriptâno manual venv or global installs. This makes sharing a one-off utility as easy as sending one file. (Python Enhancement Proposals (PEPs))
Example: GitHub stars script (single file)
Save this as github_stats.py:
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.10"
# dependencies = [
# "httpx>=0.27",
# "rich>=13.7",
# ]
# ///
import sys, httpx
from rich import print
repo = sys.argv[1] if len(sys.argv) > 1 else "python/cpython"
url = f"https://api.github.com/repos/{repo}"
data = httpx.get(url, timeout=20).json()
print(f"[bold]â {repo} stars:[/bold] {data['stargazers_count']:,}")
Run it directly:
chmod +x github_stats.py
./github_stats.py astral-sh/uv
# or
uv run github_stats.py astral-sh/uv
Behind the scenes, uv reads the PEP 723 block, creates an isolated env, installs httpx/rich, and executes. (Astral Docs)
Watch out: If you maintain both a project pyproject.toml and a PEP 723 script, youâre duplicating dependency declarations. Track this and consider tooling to sync them (thereâs active discussion in uvâs issue tracker). (GitHub)
Core Concept #3 â Ruff: linter and formatter
Ruff can replace Flake8 (+plugins), isort, and Black in one fast tool, with pyproject configuration and autofix capabilities. Itâs designed for near parity with those tools while being orders of magnitude faster. Iâve seen CI runs drop by minutes in medium repos just by switching. (Astral Docs)
Minimal pyproject.toml for Ruff
[tool.ruff]
line-length = 100
target-version = "py313"
lint.select = ["E", "F", "I", "B", "UP"] # basic errors, isort, bugbear, pyupgrade
lint.ignore = ["E501"] # example: ignore long-lines rule if desired
[tool.ruff.format]
quote-style = “double” indent-style = “space”
Run locally:
ruff check . --fix
ruff format .
Docs: Ruff supports Python 3.14 compatibility and a wide rule set with caching/autofix. (Astral Docs)
Practical Walkthrough â Modernizing an existing repo
Goal: Convert a typical pip + venv + flake8 + black + isort repo to uv + Ruff, and add a PEP 723 helper script.
- Adopt uv without breaking habits
# Create/activate a project env implicitly
uv sync # resolves & installs from pyproject, creates .venv
# Add dev tools
uv add --dev ruff
(uv provides drop-in pip flows and fast resolves.) (GitHub)
- Replace flake8/black/isort with Ruff
# remove old tool pins from pyproject/requirements
uv remove flake8 black isort # if listed
uv add --dev ruff
ruff check . --fix
ruff format .
(Parity with those tools is a design goal; configure exceptions in pyproject.toml.) (Astral Docs)
- Introduce a PEP 723 operational script
Addscripts/migrate_data.py:
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.10"
# dependencies = ["pandas>=2.2","pyarrow>=16"]
# ///
import pandas as pd
df = pd.read_parquet("input.parquet")
df.to_csv("output.csv", index=False)
print("Done.")
Run as needed without polluting your main env. (Python Enhancement Proposals (PEPs))
- CI speed-ups
- Cache uvâs directories (platform-specific), then
uv sync+ruff check+ruff format --check. - Because uv resolves and installs quickly (often 10â100Ă vs. legacy flows), CI time shrinks noticeably. (Astral Docs)
Advanced Techniques & Tips
- Script shebangs:
#!/usr/bin/env -S uv run --scriptlets teammates execute a script directly when itâs on the PATH. Great for internal CLI tools. (Astral Docs) - Pinning & reproducibility: Use uvâs lockfile and âplatform-independent resolutionsâ to keep teams in sync. (See uv docs for compile and overrides.) (GitHub)
- Targeting Python 3.13/3.14: If you experiment with free-threaded Python or the new JIT, keep an eye on ecosystem support (many packages are tracking compatibility). Start with CPU-bound, thread-friendly tasks. (Python documentation)
- One config to rule them all: Centralize tool configs in
pyproject.tomlâRuff works great there, and uv reads it for project deps. (Astral Docs)
Common Pitfalls & Solutions
- âIt still uses pip commandsâam I really using uv?â
Yes; uv exposesuv pipinterfaces as drop-in replacements with better performance. Verify withuv --version. (GitHub) - Corporate proxies/firewalls:
Configure uvâs network settings in CI and prefer index mirrors if your org requires them (see uv docs). (Astral Docs) - Duplicated deps between project and PEP 723 script:
Track both, or script a sync stepâthereâs active discussion on making this smoother. (GitHub) - Formatter differences after moving from Black:
Ruff aims for drop-in parity; check the docs and adjustpyproject.tomlwhere behavior differs. (Astral Docs)
Conclusion
Modern Python dev in 2025 is faster, simpler, and more portable. With uv youâll breeze through installs and project setup. With Ruff youâll lint and format at warp speed using one tool. And PEP 723 turns single files into self-contained, runnable programsâperfect for ops scripts, data utilities, and demos.
Next steps:
- Migrate one repo to uv + Ruff.
- Create one PEP 723 script you can share with your team.
- Experiment with Python 3.13âs free-threaded build for parallel-friendly workloads. (Astral Docs)
