In kleinen Skripten reicht oft ein kurzer print(), um zu sehen, was passiert. In echten Anwendungen mit Webserver, Datenbank und Hintergrund-Jobs funktioniert das nicht mehr: Meldungen gehen verloren, wichtige Hinweise stehen nicht im Log oder es herrscht schlicht Chaos.
Ein durchdachtes Python Logging macht Anwendungen nachvollziehbar: Fehler lassen sich schneller finden, Engpässe erkennen und sicherheitsrelevante Vorgänge protokollieren. Dieser Leitfaden zeigt Schritt für Schritt, wie Logging mit dem Standardmodul logging sauber aufgesetzt wird – von den Grundlagen bis zu produktionsreifen Setups.
Python Logging Grundlagen – Log-Level, Logger und Handler
Das in der Standardbibliothek enthaltene Modul logging reicht für viele Webanwendungen völlig aus. Es basiert auf drei zentralen Bausteinen: Logger, Handler und Formatter.
Log-Level in Python: Wann INFO, wann ERROR?
Log-Level helfen, Meldungen nach Wichtigkeit zu filtern. Die gängigen Stufen in aufsteigender Dringlichkeit:
DEBUG: Sehr detaillierte Infos für die Fehlersuche. Nur in Entwicklung oder gezielt in Produktion aktivieren.INFO: Normale Betriebsinfos – Start von Jobs, erfolgreiche Logins, abgeschlossene Bestellungen.WARNING: Unerwartete Situationen, die noch nicht kritisch sind (z. B. Timeout beim externen Dienst, Fallback genutzt).ERROR: Fehlgeschlagene Aktionen (z. B. Exception beim Speichern, aber Anwendung läuft weiter).CRITICAL: Schwere Fehler, nach denen das System möglicherweise nicht zuverlässig weiterläuft.
In produktiven Umgebungen ist ein Basis-Level von INFO üblich, kombiniert mit gezielten DEBUG-Logs in kritischen Modulen.
Logger, Handler, Formatter: Aufbau eines Log-Systems
Das Modul logging trennt Zuständigkeiten klar:
- Logger sind die Einstiegspunkte im Code. Über sie werden Meldungen geschrieben.
- Handler bestimmen, wohin Logs gehen: Konsole, Datei, E-Mail, HTTP-Endpunkt usw.
- Formatter legen fest, wie die Logzeilen aussehen – etwa mit Zeitstempel, Modulnamen und Kontextinformationen.
Ein einfaches Setup, das auf die Konsole schreibt, sieht zum Beispiel so aus:
import logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s [%(name)s] %(message)s")
logger = logging.getLogger(__name__)
logger.info("Server gestartet")
Damit ist eine erste Struktur da – aber für Webprojekte reicht diese Basis meist nicht aus.
Projektweites Logging-Konzept für Webanwendungen planen
Bevor im Code überall Logzeilen verteilt werden, lohnt ein kurzer Plan. Ein Logging-Konzept schützt davor, in unübersichtlichen Meldungen zu ertrinken oder entscheidende Informationen gar nicht zu protokollieren.
Was sollte in eine Logging-Strategie hinein?
Ein einfaches Logging-Konzept beantwortet unter anderem diese Fragen:
- Welche Ereignisse sind wichtig? (z. B. Logins, Bestellungen, API-Fehler, Performance-Spitzen)
- Welche Daten dürfen aus Datenschutzgründen nicht im Log landen? (z. B. Passwörter, komplette Kreditkartendaten)
- Wie lange sollen Logs aufbewahrt werden, und wo?
- Wer braucht Zugriff: nur Admins, auch Entwickler, externe Dienstleister?
Für Webprojekte mit mehreren Services hilft ein zentraler Blick: Logs sollten zueinander passen, damit Requests entlang der ganzen Kette nachvollziehbar bleiben. Das Prinzip ähnelt einer klaren Seitenstruktur im SEO: Ohne System geht der Überblick schnell verloren.
Typische Log-Quellen in Python-Webprojekten
In einer typischen Python-Webanwendung tauchen mehrere Log-Quellen auf:
- Webframework (z. B. Django, Flask, FastAPI)
- Datenbank-Layer (ORM-Queries, Verbindungsfehler)
- Hintergrund-Jobs (z. B. Celery, eigene Worker-Skripte)
- externe APIs (Requests, Fehlermeldungen, Timeouts)
All diese Quellen sollten sich einem einheitlichen Logging-Setup unterordnen. Der erste Schritt ist häufig, einen Logger pro Modul oder Komponente zu nutzen – etwa logger = logging.getLogger("shop.checkout").
Logging in Python sauber konfigurieren – von basicConfig bis dictConfig
Für kleine Tools mag basicConfig() genügen. Wächst das Projekt, sollte die Konfiguration in eine eigene Datei oder in Einstellungen ausgelagert werden.
Warum dictConfig für größere Projekte ideal ist
Mit logging.config.dictConfig() lässt sich die gesamte Logging-Struktur deklarativ beschreiben. Das erleichtert Änderungen und erlaubt unterschiedliche Profile für Entwicklung, Test und Produktion.
Ein vereinfachtes Beispiel:
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"standard": {
"format": "%(asctime)s %(levelname)s [%(name)s] %(message)s",
}},
"handlers": {
"console": {
"class": "logging.StreamHandler",
"formatter": "standard",
"level": "INFO",
}},
"loggers": {
"": { # Root-Logger
"handlers": ["console"],
"level": "INFO",
}},
}
Die Konfiguration kann aus einer Python-Datei, einer JSON- oder YAML-Datei geladen werden. So passt das Logging gut in bestehende Konfigurationssysteme.
Mehrere Handler kombinieren: Konsole, Datei, Monitoring
In professionellen Umgebungen reichen reine Konsolen-Logs nicht aus. Häufig sinnvoll ist eine Kombination:
- Konsolen-Handler für lokale Entwicklung und Container-Logs.
- Datei-Handler mit Rotation (z. B.
RotatingFileHandler) für lokale oder On-Premise-Setups. - Handler, die Logs an zentrale Systeme senden (z. B. HTTP, Socket oder spezielle Integrationen).
Für große Projekte kann es sich lohnen, Logs an eine zentrale Plattform zu senden und dort zu durchsuchen – ähnlich wie bei einem guten API-Monitoring mit REST-APIs.
Strukturierte Logs und Kontext – mehr als nur Textzeilen
Reine Textmeldungen helfen bei kleinen Fehlern, stoßen aber bei komplexen Webanwendungen schnell an Grenzen. Mit strukturierten Informationen in den Logs wird es einfacher, Probleme zu filtern und automatisch auszuwerten.
Kontext mit extra-Parametern hinzufügen
Python unterstützt zusätzliche Kontextdaten über das extra-Argument oder über LoggerAdapter. Ein Beispiel mit extra:
logger.info("Zahlung fehlgeschlagen", extra={"order_id": 1234, "user_id": 42})
Der Formatter kann diese Felder ausgeben, etwa mit %(order_id)s. So lassen sich Logs zum Beispiel nach Bestell-ID oder Benutzer-ID filtern, ohne diese Informationen in freie Textfelder zu quetschen.
JSON-Logging für moderne Toolchains
Viele Log-Management-Systeme arbeiten bevorzugt mit JSON, weil sich damit Felder gezielt auswerten lassen. Ein Formatter, der jede Logzeile als JSON ausgibt, macht es einfach, Events zu durchsuchen und Dashboards aufzubauen.
Ein Beispiel für eine einfache JSON-Struktur:
timestamp: ISO-8601-Zeitstempellevel: Log-Level (INFO, ERROR, …)logger: Name des Loggersmessage: eigentliche Meldungcontext: zusätzliche Felder wierequest_id,user_id,order_id
Wer noch einen Schritt weiter gehen will, kann Logging-Muster ähnlich streng gestalten wie Clean Code im Applikationsdesign – angelehnt an Prinzipien, wie sie auch in Clean Code in JavaScript genutzt werden.
Fehlerlogging und Ausnahmen richtig behandeln
Gerade bei Exceptions zeigt sich die Qualität eines Logging-Setups. Ohne Stacktrace oder Kontext sind Fehler oft schwer nachvollziehbar.
Exceptions mit Stacktrace loggen
Für Exceptions bietet Python mehrere Möglichkeiten:
logger.exception("Fehler beim Verarbeiten der Bestellung")innerhalb einesexcept-Blocks loggt automatisch die aktuelle Exception inklusive Stacktrace mit Level ERROR.logger.error("Fehler", exc_info=True)liefert ebenfalls den Stacktrace.
Wichtig ist, nicht jede Ausnahme nur zu fangen und zu verschlucken. Wenn ein Fehler im Code abgefangen wird, sollte zumindest auf WARNING oder ERROR geloggt werden, damit er beobachtbar bleibt.
Fehlerkategorien und Alarmierung
In produktiven Umgebungen genügt es nicht, Fehler nur zu protokollieren. Kritische Ereignisse sollten zu Alarmen führen – etwa über E-Mail, Chat oder ein Incident-Tool.
Praktischer Ansatz:
- Normale Fehler als
ERRORloggen. - Systembedrohende Zustände (z. B. Datenbank nicht erreichbar) zusätzlich mit einem speziellen Handler an ein Monitoring-System schicken.
- Im Monitoring Alarm-Regeln basierend auf Anzahl und Art der Logeinträge definieren.
Praxis-Checkliste: Robust logging in Python-Projekten aufbauen
Die folgenden Punkte dienen als kompakte Checkliste für neue oder bestehende Projekte.
| Bereich | Frage | Hinweis |
|---|---|---|
| Log-Level | Ist das Standard-Level sinnvoll gewählt? | In Produktion meist INFO, DEBUG nur gezielt. |
| Struktur | Gibt es Logger pro Modul/Komponente? | Namen wie shop.checkout oder api.v1.orders nutzen. |
| Ausgabeziele | Werden Konsole und Dateien/Remote-Logs sinnvoll kombiniert? | Rotation für Dateien, zentrale Sammlung für Analyse. |
| Kontext | Werden request_id, user_id etc. mitgeloggt? | Kontext über Formatter oder LoggerAdapter anreichern. |
| Datenschutz | Werden sensible Daten ausgeschlossen? | Keine Passwörter, vollständige Kreditkartendaten oder Tokens loggen. |
| Fehler | Werden Exceptions mit Stacktrace erfasst? | logger.exception() im except-Block verwenden. |
So geht’s: Eigene Logging-Basis in einem Tag aufsetzen
- Logging-Bedarf notieren: Welche Bereiche der Anwendung sind kritisch (Zahlung, Login, API-Aufrufe)?
- Ein zentrales
LOGGING-Dict mitdictConfiganlegen: Format, Handler für Konsole und ggf. Dateien oder Remote-Logs definieren. - In jedem Modul einen Logger mit sprechendem Namen anlegen, z. B.
logging.getLogger("shop.checkout"). - Bestehende
print()-Aufrufe durch passendelogger.debug/info/warning/errorersetzen. - Exceptions konsequent mit
logger.exception()loggen und kritischste Meldungen im Monitoring sichtbar machen.
Logging im Team etablieren – Konventionen und Code-Reviews
Selbst das beste Setup nützt wenig, wenn jede Entwicklerin und jeder Entwickler andere Log-Gewohnheiten hat. Gemeinsame Regeln sorgen für konsistente und aussagekräftige Logs.
Teamregeln für Log-Nachrichten definieren
Ein kleines Styleguide-Dokument reicht oft schon:
- Welche Sprachen und Formulierungen werden genutzt? (z. B. immer auf Deutsch oder Englisch, keine Abkürzungs-Wildwuchs).
- Welche Informationen sollten in bestimmten Situationen immer mitgeloggt werden? (z. B. request_id bei HTTP-Fehlern).
- Wie werden sensible Daten anonymisiert oder gehasht?
Solche Regeln können in Code-Reviews überprüft werden – ähnlich wie es bei Typografie-Regeln in Layout-Projekten mit Absatzformaten in InDesign geschieht.
Logs regelmäßig auswerten – nicht nur im Ernstfall
Logs sind nicht nur im Katastrophenfall hilfreich. Wer sie regelmäßig durchgeht, entdeckt Muster:
- wiederkehrende Warnungen, die auf zukünftige Probleme hinweisen,
- Performance-Hinweise, z. B. ungewöhnlich lange Requests,
- Nutzungsverhalten, etwa besonders häufig genutzte API-Endpunkte.
Ein fester Termin im Sprint-Rhythmus, bei dem Log-Trends durchgegangen werden, kann die Qualität einer Anwendung nachhaltig verbessern.
FAQ zu Python Logging im Webprojekt
- Wie viele Logzeilen sind „zu viel“?
Das hängt stark von Projekt und Infrastruktur ab. Wichtig ist, dass Logs fokussiert bleiben: Wiederholte, irrelevante Meldungen lieber reduzieren oder das Level anpassen. - Reicht Logging oder braucht es zusätzlich Tracing?
Logging beantwortet vor allem „Was ist passiert?“. Tracing ergänzt „Wie lange hat es gedauert und wo genau?“ – beides zusammen ergibt ein solides Bild. - Sollte Logging synchron oder asynchron sein?
Für die meisten Webanwendungen ist synchrones Logging ausreichend. Bei sehr hohem Durchsatz oder langsamen Log-Zielen (Netzwerk) kann asynchrones Logging über Warteschlangen sinnvoll sein.

