Die Python-Paketverwaltung war über Jahre hinweg ein fragmentiertes Ökosystem. Wer professionelle Projekte aufsetzen wollte, jonglierte meist mit pyenv für die Python-Versionen, venv für isolierte Umgebungen, pip für die Installation und pip-tools für die Erstellung von Lock-Files. uv von Astral ist ein Paketmanager in Python, der nicht nur durch seine hohe Geschwindigkeit überzeugt sondern darüber hinaus auch das komplette Projektmanagement unterstützt.
uv verfolgt eine radikale Konsolidierungsstrategie und ersetzt nicht nur pip sondern ermöglicht auch das Management der pyproject.toml und das erstellen von virtuellen Umgebungen.
Die Kernvorteile auf einen Blick:
- Extreme Geschwindigkeit: Installationen und Auflösungen sind 10- bis 100-mal schneller als bei pip.
- Tool-Konsolidierung: Ersetzt pip, pip-tools, pipx, poetry, pyenv und virtualenv vollständig.
- Zuverlässigkeit: Standardmäßige Erzeugung einer universellen, plattformübergreifenden Lock-Datei.
- Integriertes Python-Management:
uvlädt bei Bedarf automatisch die passende Python-Version herunter.
Installation und Projekt-Initialisierung
Installation
Der schnellste Weg (Einzeiler)
Für macOS und Linux nutzt du einfach das offizielle Installationsskript:
curl -LsSf https://astral.sh/uv/install.sh | sh
Für Windows (PowerShell) gibt es ebenfalls einen bequemen Befehl:
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
Alternative über Paketmanager
Wenn du deine Software lieber zentral verwaltest, kannst du die gängigen Tools nutzen:
- macOS (Homebrew):
brew install uv - Windows (Scoop):
scoop install uv - Windows (Winget):
winget install astral-sh.uv - Linux (pipx): Falls du
pipxbereits hast, geht auchpipx install uv(obwohl das Skript oben meist sauberer ist, da es keine Python-Abhängigkeit erzeugt).
Update nach der Installation
Sobald uv auf deinem Rechner ist, musst kann man das Tool einfach sich selbst aktualisieren lassen:
uv self update
Projekt Initialisierung
Mit uv init erstellt man eine konsistente Projektstruktur, die modernen Standards entspricht.
mkdir mein_projekt
cd mein_projekt
uv initNutze man den Flag uv init --lib so wird direkt ein src-Layout generiert. Dieser Standard ist ein Best Practice, da er den Quellcode isoliert und verhindert, dass lokale Ordner versehentlich importiert werden, anstatt des tatsächlich installierten Pakets.
uv init --lib In uv kann man zudem direkt eine gewünschte Python-Version festlegen:
uv python pin 3.14Grundgerüst
Der Befehl uv init erzeugt ein schlankes Grundgerüst. Hier ist die Übersicht der Dateien und ihrer strategischen Bedeutung:
- pyproject.toml Die zentrale Schaltstelle für Metadaten, Build-System und Abhängigkeiten.
- .python-version Der „Source of Truth“ für die Python-Version. uv nutzt dies, um die korrekte CPython-Version automatisch bereitzustellen.
- README.md Dokumentationsbasis für das Projekt.
- .gitignore Vorkonfiguriert, um Artefakte wie .venv sicher aus der Versionskontrolle auszuschließen.
- main.py Der Standard-Einstiegspunkt
Pyproject.toml
Die pyproject.toml hat die veraltete requirements.txt abgelöst. Sie ist der moderne Standard (PEP 518/621), um Portabilität und Konsistenz zu garantieren.
Beispiel A: Statische Konfiguration (Einfache App)
Ideal für schnelle Projekte, bei denen die Version direkt in der Datei steht.
[project]
name = "mein-projekt"
version = "0.1.0"
description = "Ein modernes Python-Projekt"
requires-python = ">=3.12"
dependencies = []Beispiel B: Dynamische Metadaten (Professionelle Library)
Häufig wird die Version im Quellcode gepflegt (z. B. in init.py). Hier hilft dynamische Auflösung:
[project]
name = "mein-projekt"
dynamic = ["version"]
requires-python = ">=3.12"
dependencies = []
[tool.setuptools.dynamic]
version = {attr = "mein_projekt.version"}Dependency Management
Installieren von Paketen
Der Befehl uv add ist mehr als ein bloßer Installationsbefehl. Er löst Abhängigkeiten auf, aktualisiert die pyproject.toml und synchronisiert sofort die virtuelle Umgebung (.venv). Zur Installation des Python-Pakets ‚requests‘ sieht das so aus:
uv add requestsWenn man das Paket requests wieder aus deinem Projekt werfen möchtest, tippst man einfach:
uv remove requestsDependency Groups
Ein weiteres mächtiges Feature ist das Handling von Entwicklungs-Abhängigkeiten. Mit uv add –dev pytest nutzt uv moderne Standards wie PEP 735 (Dependency Groups). Deine Dev-Tools landen sauber in einer [dependency-groups] Tabelle in der pyproject.toml, statt die regulären Abhängigkeiten zu verschmutzen. Dadurch werden beispielsweise Entwicklungstools wie pytest oder ruff nicht in produktive Umgebungen wie bspw. Docker-Container deployed.
uv add --dev pytest- Lokal (Entwicklung): uv sync (installiert alles inklusive Dev-Tools).
- Produktion / CI: uv sync –no-dev (erzeugt eine minimale Umgebung ohne Overhead).
- Pro-Tipp für CI: Nutzen Sie uv sync –frozen, um sicherzustellen, dass die Lock-Datei während des CI-Laufs nicht versehentlich aktualisiert wird.
uv.lock
Im Hintergrund generiert uv die Datei uv.lock. Während die pyproject.toml deine groben Anforderungen definiert, speichert die Datei uv.lock zudem die exakt aufgelösten Versionen aller direkten und transitiven Abhängigkeiten (also der installieren Pakete).
Die uv.lock ist dabei plattformunabhängig. Im Gegensatz zu alten requirements.txt-Ansätzen, die oft für Windows und Linux separat gepflegt werden mussten, deckt eine einzige uv.lock alle Zielplattformen ab. Das bedeutet, sie enthält Auflösungen für alle Plattformen (Windows, macOS, Linux).
Die uv.lock gehört zwingend in die Versionskontrolle (Git). Sie garantiert „Reproducible Environments“. Jedes Teammitglied und jeder CI-Server arbeitet dadurch mit exakt denselben Byte-identischen Abhängigkeiten.
Best Practice: Die uv.lock sollte niemals manuell bearbeitet werden.
Workflow
Der Befehl uv run garantiert, dass die Umgebung exakt mit der Lock-Datei synchronisiert ist, bevor dein Code ausgeführt wird. Falls eine Abhängigkeit fehlt, wird sie im Hintergrund in Millisekunden nachinstalliert – ein völlig reibungsloses Erlebnis.
uv runuv macht damit die manuelle Aktivierung von virtuellen Umgebungen (source .venv/bin/activate) weitgehend obsolet.
uv run: Der sicherste Weg, Code auszuführen. uv prüft vorab, ob die Umgebung mit der Lock-Datei übereinstimmt.uvx: (Ehemals uv tool run) Führt CLI-Tools wie ruff oder black in einer isolierten, temporären Umgebung aus, ohne sie als Projektabhängigkeit hinzufügen zu müssen.uv sync: Gleicht die lokale .venv manuell mit der uv.lock ab (essentiell nach einem git pull).uv lock --upgrade-package: Aktualisiert gezielt ein Paket, während die restliche Umgebung stabil bleibt.
Lokale Pakete und editable Installs
Früher war es notwendig lokale pakete mit pip install -e zu installieren.
In uv wird dies ebenfalls mit abgedeckt. Wenn du ein lokales Paket (z. B. ein Untermodul oder eine Library, an der du parallel arbeitest) einbinden willst, nutzt du:
uv add --editable ../pfad/zu/deinem/lokalen-paketuv fügt einen Eintrag in deine pyproject.toml unter dependencies hinzu, der etwa so aussieht:
dependencies = [
"mein-lokales-paket @ { root = \"../pfad/zu/deinem/lokalen-paket\" }",
]Dadurch ist das Paket im Editable Mode verknüpft. Änderungen am Code im lokalen Paket sind sofort in deinem Hauptprojekt wirksam, ohne dass du neu installieren musst.
Best Practice: Achte darauf, dass dein lokales Paket selbst eine
pyproject.tomlhat, damituverkennt, dass es ein installierbares Python-Paket ist.
Einweg-Skripte mit PEP 723 (Script Dependencies)
Oft schreibt man ein kurzes Analyse-Skript, das nur pandas und matplotlib braucht. Früher musste man dafür extra ein venv anlegen oder hoffen, dass die Pakete im Global-Environment sind.
Mit uv kannst du die Abhängigkeiten direkt im Kopf des Skripts definieren:
Python
# /// script
# requires-python = ">=3.12"
# dependencies = [
# "pandas",
# "matplotlib",
# ]
# ///
import pandas as pd
import matplotlib.pyplot as plt
print("Läuft ohne manuelles venv!")
Der Workflow: Du führst das Skript einfach mit uv run mein_skript.py aus.
uverkennt den Header.- Erstellt blitzschnell eine temporäre Umgebung.
- Installiert die Pakete (falls nicht im Cache).
- Führt das Skript aus.
Vorteil: Du kannst das Skript einem Kollegen schicken, und er braucht nur uv, um es exakt so auszuführen wie du – ohne requirements.txt oder Projektstruktur.
uv in Docker
In der Data Science ist Docker der Standard für Deployments. uv ist hier ein Gamechanger, weil es in Rust geschrieben ist und als statisches Binary kommt. Ein typischer Multi-Stage-Build sieht so aus:
Dockerfile
FROM python:3.12-slim
# Installiere uv
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
# Projekt kopieren
WORKDIR /app
COPY pyproject.toml uv.lock ./
# Abhängigkeiten installieren (ohne das Projekt selbst)
RUN uv sync --frozen --no-install-project --no-dev
# Restlichen Code kopieren
COPY . .
# App starten
CMD ["uv", "run", "python", "main.py"]
Warum das besser ist:
- Caching: Durch
--no-install-projectnutzt Docker den Layer-Cache für die Libraries optimal. Wenn du nur Code änderst, aber keine Pakete, dauert der Rebuild nur Sekunden. - Kein venv-Stress: Du musst dich nicht um
PATH-Variablen für virtuelle Umgebungen kümmern;uv runfindet alles automatisch. - Größe: Das
uv-Binary ist winzig im Vergleich zupoetryoder voll installiertenpip-tools.
Bestehende Projekte auf uv umziehen
Schritt 1: Das Projekt „uv-ifizieren“
Zuerst musst du uv mitteilen, dass dieses Verzeichnis nun ein uv-Projekt ist. Gehe in deinen Projektordner und führe aus:
Bash
uv init
Was passiert? uv erstellt eine pyproject.toml (falls keine da ist) und eine .python-version. Falls du schon eine pyproject.toml hast, bleibt diese erhalten und wird lediglich um uv-spezifische Metadaten ergänzt.
Schritt 2: Abhängigkeiten migrieren
Je nachdem, was du vorher genutzt hast, gibt es unterschiedliche Wege:
A. Von requirements.txt (Der Klassiker)
Man kann seine alten Requirements einfach in die neue pyproject.toml „einlesen“:
uv add -r requirements.txt
Falls du separate Files für die Entwicklung hattest:
uv add -r dev-requirements.txt --dev
B. Von Poetry oder Pipenv
uv versteht die pyproject.toml von Poetry bereits weitgehend. Man musst oft gar nichts tun, außer einmal uv synch auszuführen. uv erkennt die Abhängigkeiten und erstellt daraus die neue, blitzschnelle uv.lock.
uv sync
Schritt 3: Die alte Umgebung „entsorgen“
Damit es keine Konflikte gibt, solltest du den alten .venv-Ordner (oder wo auch immer deine virtuelle Umgebung lag) löschen:
rm -rf .venv # Unter Linux/Mac
rmdir /s /q .venv # Unter Windows
Führe danach einfach uv synch aus. uv erstellt eine frische, optimierte virtuelle Umgebung und installiert alle Pakete aus dem Cache (was meist nur Millisekunden dauert).
uv sync
Schritt 4: Altlasten entfernen
Sobald alles läuft, kannst du die alten Dateien löschen, die uv jetzt obsolet macht:
requirements.txt/dev-requirements.txtPipfile/Pipfile.lockpoetry.lock(Wichtig:pyproject.tomlbehalten, aber Poetry-spezifische Sektionen können später aufgeräumt werden)..python-version(Falls du sie vorher manuell gepflegt hast,uvmanaged das jetzt).
Checkliste
uv init: Projektstruktur vorbereiten.uv add -r ...: Bestehende Abhängigkeiten importieren.uv sync: Neue, saubere.venvunduv.lockerzeugen.- Testen: Mit
uv run pytestprüfen, ob alles wie gewohnt läuft. - Clean-up: Alte Lock-Files und Requirements-Dateien aus Git entfernen.