Die Python-Standardbibliothek bringt Werkzeuge mit, die viele Aufgaben ohne Zusatzpaket lösen: Dateisystem, Textverarbeitung, Datenformate, Nebenläufigkeit, Netzwerk. Wer sie kennt, schreibt kürzere Programme mit weniger Abhängigkeiten. Dieser Artikel stellt die Module vor, die in der Praxis am häufigsten gebraucht werden.
Pfade und Dateisystem: pathlib statt os.path
from pathlib import Path
p = Path("/srv/daten")
datei = p / "bericht" / "2026-09.txt" # Zusammenfuegen mit /
print(datei.suffix) # .txt
print(datei.stem) # 2026-09
print(datei.parent) # /srv/daten/bericht
# Lesen und schreiben (kuerzer als open/close)
text = datei.read_text(encoding="utf-8")
datei.write_text("Inhalt\n", encoding="utf-8")
daten = datei.read_bytes()
# Verzeichnisse durchlaufen
for f in Path("/var/log").glob("*.log"):
print(f.name, f.stat().st_size)
for f in Path("/var/log").rglob("*.gz"): # rekursiv
print(f)
# Anlegen, verschieben, loeschen
Path("/tmp/neu").mkdir(parents=True, exist_ok=True)
Path("/tmp/neu/a.txt").touch()
# Umbenennen/Verschieben
Path("/tmp/neu/a.txt").rename("/tmp/neu/b.txt")
# Aufraeumen (Vorsicht!)
# shutil.rmtree(Path("/tmp/neu"))
# Metadaten
st = datei.stat()
print(st.st_size, st.st_mtime)
print(datei.exists(), datei.is_file(), datei.is_dir())
pathlib ist der deutlich angenehmere Weg als die alten os.path-Funktionen: Pfade sind Objekte mit Methoden statt Zeichenketten mit Trennzeichen. Für das Kopieren ganzer Bäume bleibt shutil zuständig.
import shutil
shutil.copy2("/etc/hosts", "/tmp/hosts.bak") # mit Metadaten
shutil.copytree("/srv/app", "/srv/app.bak")
shutil.move("/tmp/x", "/srv/x")
total, used, free = shutil.disk_usage("/")
print(f"frei: {free/1024**3:.1f} GB von {total/1024**3:.1f} GB")
JSON und CSV
import json, csv
# JSON lesen und schreiben
daten = {"server": [{"name": "web01", "ip": "10.0.0.11"}]}
text = json.dumps(daten, indent=2, ensure_ascii=False)
geladen = json.loads(text)
from pathlib import Path
Path("/tmp/s.json").write_text(text, encoding="utf-8")
inhalt = json.loads(Path("/tmp/s.json").read_text(encoding="utf-8"))
# Wichtige Parameter
json.dumps(daten, indent=2) # lesbar formatiert
json.dumps(daten, ensure_ascii=False) # Umlaute bleiben Umlaute
json.dumps(daten, sort_keys=True) # stabile Reihenfolge (Tests!)
# CSV lesen
with open("/tmp/daten.csv", newline="", encoding="utf-8") as f:
for zeile in csv.DictReader(f):
print(zeile["name"], zeile["ip"])
# CSV schreiben
with open("/tmp/out.csv", "w", newline="", encoding="utf-8") as f:
w = csv.DictWriter(f, fieldnames=["name", "ip"])
w.writeheader()
w.writerow({"name": "web01", "ip": "10.0.0.11"})
# Aufgaben mit Zitaten, Semikolons, Tabellen
csv.reader(f, delimiter=";", quotechar='"')
csv.reader(f, delimiter="\t")
Wichtig beim CSV-Schreiben: newline="" ist Pflicht, sonst entstehen unter Windows doppelte Zeilenumbrüche. Und encoding="utf-8" immer angeben – die Standardkodierung ist plattformabhängig.
Kommandozeilenargumente: argparse
import argparse
p = argparse.ArgumentParser(
prog="backup",
description="Sichert Verzeichnisse als Archiv.")
p.add_argument("quelle", help="zu sicherndes Verzeichnis")
p.add_argument("-z", "--ziel", default="/srv/backup",
help="Zielverzeichnis (Standard: %(default)s)")
p.add_argument("-k", "--komprimierung", choices=["none","gzip","zstd"],
default="gzip")
p.add_argument("-v", "--verbose", action="store_true",
help="ausfuehrliche Ausgabe")
p.add_argument("--trocken", action="store_true",
help="nur anzeigen, nichts schreiben")
args = p.parse_args()
if args.verbose:
print(f"Sichere {args.quelle} nach {args.ziel}")
# Aufruf: python backup.py /etc -z /srv/backup -k zstd -v
# --help wird automatisch erzeugt
Subprozesse: externes Programm aufrufen
import subprocess
# Empfohlen: Liste von Argumenten, keine Shell
r = subprocess.run(["df", "-h"], capture_output=True, text=True, timeout=10)
print(r.returncode)
print(r.stdout)
# Mit Fehlerpruefung
try:
subprocess.run(["systemctl", "is-active", "--quiet", "nginx"],
check=True, timeout=5)
print("laeuft")
except subprocess.CalledProcessError:
print("laeuft nicht")
# Shell nur, wenn wirklich noetig (Pipes, Umleitung)
r = subprocess.run("df -h | tail -1", shell=True, capture_output=True, text=True)
# WICHTIG: Niemals Nutzereingaben mit shell=True verkettet verwenden.
# Das ist der klassische Weg zur Kommando-Einschleusung.
# SCHLECHT: subprocess.run(f"ping {host}", shell=True)
# GUT: subprocess.run(["ping", "-c", "1", host], timeout=5)
Datum und Zeit
from datetime import datetime, timedelta, timezone
jetzt = datetime.now(timezone.utc) # immer mit Zeitzone!
print(jetzt.isoformat()) # 2026-09-26T21:30:00+00:00
# Rechnen
morgen = jetzt + timedelta(days=1)
vorwoche = jetzt - timedelta(weeks=1)
# Formatieren und parsen
print(jetzt.strftime("%Y-%m-%d %H:%M:%S"))
d = datetime.strptime("2026-09-26 14:30", "%Y-%m-%d %H:%M")
# Zeitzonen
from zoneinfo import ZoneInfo
berlin = jetzt.astimezone(ZoneInfo("Europe/Berlin"))
# Fuer Zeitmessungen: perf_counter statt now()
import time
t0 = time.perf_counter()
# ... arbeit ...
print(f"{(time.perf_counter()-t0)*1000:.1f} ms")
Regel: Immer zeitzonenbewusste Zeitstempel verwenden. Ein datetime.now() ohne Zeitzone ist die Quelle unzähliger Fehler bei der Auswertung von Protokollen.
Weitere Module, die Zeit sparen
collections:defaultdict(Wörterbuch mit Standardwert),Counter(zählen),deque(schnelle Warteschlange an beiden Enden),namedtuple.itertools:chain,groupby,islice,combinations– mächtige Bausteine ohne eigene Schleifen.re: Reguläre Ausdrücke. Immer mitre.compile()vorbereiten, wenn dieselbe Suche mehrfach läuft, undr"..."für das Muster verwenden.logging: Protokollierung stattprint. Mitlogging.basicConfig(level=logging.INFO)und Formatangabe lässt sich der Detaillierungsgrad über die Umgebung steuern.dataclasses:@dataclasserzeugt Konstruktor, Vergleich und Darstellung automatisch – ideal für Konfigurations- und Datenklassen.functools:lru_cachefür Ergebnisse teurer Funktionen,partialfür vorbelegte Argumente.hashlibundsecrets: Prüfsummen und Zufallswerte. Für Kennwörter und Token immersecretsstattrandom.urllib.parse: Adressen zusammensetzen und zerlegen – sicherer als Zeichenkettenverkettung.tempfile:NamedTemporaryFileundTemporaryDirectoryräumen sich selbst auf.
# Beispiele fuer die wichtigsten
from collections import defaultdict, Counter
zaehler = Counter(["a","b","a","c","a"]) # Counter({'a': 3, ...})
nach_host = defaultdict(list)
nach_host["web01"].append("nginx") # kein KeyError
from dataclasses import dataclass, field
@dataclass
class Server:
name: str
ip: str
dienste: list[str] = field(default_factory=list)
s = Server("web01", "10.0.0.11")
print(s) # Server(name='web01', ip='10.0.0.11', dienste=[])
from functools import lru_cache
@lru_cache(maxsize=128)
def teuer(n):
return sum(i*i for i in range(n))
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s")
logging.info("gestartet")
Wann ein Zusatzpaket sinnvoll ist
Die Standardbibliothek deckt vieles, aber nicht alles ab. Für diese Aufgaben lohnt sich ein bewährtes Zusatzpaket:
- HTTP-Anfragen:
requestsoderhttpx– deutlich angenehmer alsurllib.request. - Tabellen und Zahlen:
pandasundnumpy. - Kommandozeile ohne Konfiguration:
typerleitet die Schnittstelle aus Typhinweisen ab. - Datenprüfung:
pydanticfür Konfiguration und API-Eingaben. - Tests:
pyteststattunittest– kürzer und aussagekräftiger.
Verwandte Grundlagen: Python: Funktionen und Module, Python: Dateien lesen und schreiben, python-Befehle, Python: Exceptions.