cat posts/logging-statt-print.md
Logging statt print
print hilft beim schnellen Nachsehen, logging begleitet laufende Programme: Levels, Logger pro Modul, Formatierung, Dateien und Tracebacks.
print(...) ist großartig, wenn Du schnell etwas im Terminal sehen möchtest.
print("Bin hier")
print(spieler.hp)
print("Speichern fertig")
Für kleine Experimente ist das völlig in Ordnung. Sobald ein Programm aber
länger läuft oder von anderen benutzt wird, stößt print(...) schnell an seine
Grenzen.
Ein Cronjob, ein Webdienst, ein Bot oder ein größeres Tool soll nicht einfach irgendwelche Ausgaben ins Terminal werfen. Es soll nachvollziehbar melden:
- was passiert ist,
- wann es passiert ist,
- wo im Programm es passiert ist,
- wie wichtig die Meldung ist,
- ob ein Fehler mit Traceback aufgetreten ist.
Dafür gibt es in Python das Standardmodul logging.
In Teil 8 der Python-Serie ging es um Exceptions und Fehlerbehandlung. Logging beantwortet die nächste wichtige Frage:
Was ist vor dem Fehler passiert?
Warum print(...) nicht reicht
Mit print(...) kannst Du schnell einen Wert anzeigen:
print(f"Spieler: {spieler.name}")
Das ist direkt, einfach und für Lerncode nützlich.
In einem dauerhaft laufenden Programm fehlen aber wichtige Eigenschaften.
Keine Wichtigkeit
Diese Ausgaben sehen gleich wichtig aus:
print("Spiel gestartet")
print("Spielstand gespeichert")
print("Spielstand konnte nicht geladen werden")
print("Datenbank nicht erreichbar")
Als Mensch erkennst Du vielleicht aus dem Text, was ernst ist. Ein Programm, ein Monitoring oder ein Log-Viewer erkennt es nicht automatisch.
Logging kennt dafür Levels.
Keine zentrale Steuerung
Mit print(...) musst Du jede einzelne Ausgabe anfassen, wenn Du sie entfernen,
umleiten oder anders darstellen möchtest.
Bei Logging kannst Du zentral festlegen:
- ab welchem Level Meldungen erscheinen,
- ob sie auf der Konsole ausgegeben werden,
- ob sie in eine Datei geschrieben werden,
- wie jede Logzeile formatiert wird.
Der Code, der loggt, muss dafür nicht geändert werden.
Kein automatischer Kontext
Mit print(...) müsstest Du Zeitstempel, Modulnamen oder Levels von Hand
ergänzen:
print("[INFO] dungeon.save: Spielstand gespeichert")
Das ist fehleranfällig und wird schnell uneinheitlich.
Logging kann diesen Kontext automatisch liefern.
Ein erstes Logging-Beispiel
Das Modul heißt logging:
import logging
Die einfachste Verwendung sieht so aus:
import logging
logging.warning("Etwas ist seltsam.")
logging.error("Eine Operation ist fehlgeschlagen.")
Die Ausgabe sieht ungefähr so aus:
WARNING:root:Etwas ist seltsam.
ERROR:root:Eine Operation ist fehlgeschlagen.
Ohne weitere Konfiguration zeigt Python standardmäßig nur Meldungen ab
WARNING an.
Diese Meldung erscheint deshalb zunächst nicht:
logging.info("Spiel gestartet.")
Damit INFO-Meldungen sichtbar werden, konfigurieren wir Logging.
Logging konfigurieren mit basicConfig(...)
Für ein Skript reicht zu Beginn häufig logging.basicConfig(...):
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
)
logging.info("Spiel gestartet.")
Eine mögliche Ausgabe:
2026-07-29 14:30:00,123 INFO root: Spiel gestartet.
Die wichtigsten Bestandteile:
| Einstellung | Bedeutung |
|---|---|
level |
niedrigstes Level, das ausgegeben wird |
format |
Aufbau jeder Logzeile |
%(asctime)s |
Zeitstempel |
%(levelname)s |
Levelname |
%(name)s |
Logger-Name |
%(message)s |
eigentliche Nachricht |
basicConfig(...) sollte möglichst einmal zentral beim Programmstart aufgerufen
werden.
In einem größeren Projekt passiert das typischerweise in der Anwendung, nicht in einzelnen Modulen.
Die wichtigsten Logging-Levels
Logging kennt mehrere Stufen.
| Level | Verwendung |
|---|---|
DEBUG |
sehr detaillierte Informationen für die Fehlersuche |
INFO |
normale Ereignisse im Programmablauf |
WARNING |
etwas Unerwartetes, aber das Programm kann weiterlaufen |
ERROR |
eine Operation ist fehlgeschlagen |
CRITICAL |
schwerer Fehler, Programm oder Dienst kann möglicherweise nicht weiterarbeiten |
Beispiel:
import logging
logging.debug("Raumdaten geladen: %s", raum_id)
logging.info("Spiel gestartet")
logging.warning("Spielstand fehlt, neues Spiel wird begonnen")
logging.error("Spielstand konnte nicht gespeichert werden")
logging.critical("Konfiguration fehlt, Programm wird beendet")
Setzt Du das Level auf INFO, erscheinen INFO, WARNING, ERROR und
CRITICAL.
logging.basicConfig(level=logging.INFO)
DEBUG wird dann ausgefiltert.
Setzt Du das Level auf WARNING, erscheinen nur noch WARNING, ERROR und
CRITICAL.
logging.basicConfig(level=logging.WARNING)
Das ist der große Vorteil gegenüber print(...): Die Logzeilen bleiben im Code,
aber Du steuerst zentral, welche davon tatsächlich ausgegeben werden.
Ein Logger pro Modul
Für kurze Skripte funktionieren die direkten Funktionen:
logging.info("Spiel gestartet")
Sie verwenden den sogenannten Root-Logger.
In Modulen und größeren Programmen ist diese Schreibweise üblicher:
import logging
logger = logging.getLogger(__name__)
Danach verwendest Du den Logger:
logger.info("Spiel gestartet")
logger.warning("Kein Spielstand gefunden")
__name__ enthält den Namen des aktuellen Moduls.
In einer Datei speichern.py wäre der Logger-Name beispielsweise:
speichern
In einem Package könnte er so aussehen:
dungeon.speichern
Dadurch erkennst Du später im Log, aus welchem Modul eine Meldung stammt.
Logger-Hierarchie
Logger-Namen bilden eine Hierarchie.
Ein Logger namens
dungeon.speichern
liegt unterhalb von:
dungeon
Und dieser wiederum unterhalb des Root-Loggers.
Das ist praktisch, weil Du später gezielt steuern kannst:
logging.getLogger("dungeon.speichern").setLevel(logging.DEBUG)
logging.getLogger("dungeon").setLevel(logging.INFO)
So könntest Du für ein bestimmtes Modul mehr Details einschalten, ohne das
gesamte Programm auf DEBUG zu setzen.
Für den Einstieg reicht die Konvention:
logger = logging.getLogger(__name__)
Nachrichten richtig formatieren
Bei print(...) würdest Du oft f-Strings verwenden:
print(f"Spielstand für {spieler.name} gespeichert")
Beim Logging ist diese Schreibweise besser:
logger.info("Spielstand für %s gespeichert", spieler.name)
Das sieht zunächst ungewohnt aus, hat aber einen Vorteil: Logging kann die Nachricht verzögert zusammensetzen.
Wenn das Level ausgefiltert wird, muss die vollständige Nachricht nicht unbedingt gebaut werden.
Schlecht:
logger.debug(f"Raumdaten: {raeume}")
Besser:
logger.debug("Raumdaten: %s", raeume)
Gerade bei DEBUG-Logs, die im normalen Betrieb häufig deaktiviert sind, ist
das sinnvoll.
Für einfache Werte ist der Unterschied meist klein. Die Logging-Schreibweise mit
%s ist trotzdem die übliche Form.
Logging mit Kontext
Mehrere Werte werden als zusätzliche Argumente übergeben:
logger.info(
"Spielstand gespeichert: spieler=%s ort=%s",
spieler.name,
ort,
)
Ausgabe:
2026-07-29 14:30:00,123 INFO __main__: Spielstand gespeichert: spieler=Karl ort=halle
Du kannst auch strukturiert loggen:
logger.debug(
"Befehl verarbeitet: verb=%s argument=%s ort=%s",
verb,
argument,
ort,
)
Das ist oft besser als eine sehr freie Textmeldung, weil wichtige Werte konsistent auftauchen.
Exceptions loggen
In einem except-Block möchtest Du häufig nicht nur eine freundliche Meldung
ausgeben, sondern den vollständigen Traceback festhalten.
Dafür gibt es logger.exception(...):
try:
lade_spielstand()
except SpielstandError:
logger.exception("Spielstand konnte nicht geladen werden")
print("Der Spielstand konnte nicht geladen werden.")
logger.exception(...) loggt mit Level ERROR und hängt automatisch die
Exception-Informationen inklusive Traceback an.
Wichtig: Verwende logger.exception(...) innerhalb eines except-Blocks. Nur
dort gibt es eine aktuelle Exception, deren Traceback sinnvoll angehängt werden
kann.
Außerhalb eines except-Blocks verwendest Du normalerweise:
logger.error("Spielstand konnte nicht geladen werden")
Oder ausdrücklich:
logger.error("Spielstand konnte nicht geladen werden", exc_info=True)
logger.exception(...) ist praktisch eine Kurzform für logger.error(...,
exc_info=True) innerhalb eines Exception-Handlers.
Erwartete Fehler nicht immer als Traceback loggen
Nicht jeder abgefangene Fehler ist automatisch ein technischer Fehler.
Wenn ein Spieler nimm drachenei eingibt und im Raum kein Drachenei liegt, ist
das eine erwartbare Benutzereingabe.
Dafür reicht vielleicht:
logger.info("Unmögliche Aktion: %s", fehler)
print(fehler)
Ein vollständiger Traceback wäre hier eher Lärm.
Anders ist es bei unerwarteten Fehlern beim Speichern:
try:
speichere_spielstand(...)
except SpielstandError:
logger.exception("Speichern fehlgeschlagen")
print("Der Spielstand konnte nicht gespeichert werden.")
Als Faustregel:
- Erwartbare Benutzerfehler: eher
INFOoderWARNING, meist ohne Traceback. - Unerwartete technische Fehler:
ERRORoderCRITICAL, oft mit Traceback.
In Dateien loggen
basicConfig(...) kann Logs direkt in eine Datei schreiben:
import logging
logging.basicConfig(
filename="dungeon.log",
encoding="utf-8",
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
)
Nun landen die Logmeldungen in dungeon.log.
Standardmäßig wird an die Datei angehängt. Möchtest Du die Datei bei jedem Start neu schreiben, setzt Du:
filemode="w"
Beispiel:
logging.basicConfig(
filename="dungeon.log",
filemode="w",
encoding="utf-8",
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
)
Für einfache Skripte ist das ausreichend.
Gleichzeitig auf Konsole und in Datei loggen
Manchmal möchtest Du Logs sowohl im Terminal sehen als auch in eine Datei schreiben.
Das geht mit mehreren Handlern:
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
handlers=[
logging.StreamHandler(),
logging.FileHandler(
"dungeon.log",
encoding="utf-8",
),
],
)
Ein Handler entscheidet, wohin Log-Records geschrieben werden.
Typische Handler sind:
| Handler | Ziel |
|---|---|
StreamHandler |
Konsole beziehungsweise Stream |
FileHandler |
Datei |
RotatingFileHandler |
Datei mit Größenrotation |
TimedRotatingFileHandler |
Datei mit Zeitrotation |
Für ein kleines Projekt reichen StreamHandler und FileHandler.
Rotierende Logdateien
Eine dauerhaft laufende Anwendung sollte nicht endlos in dieselbe Datei schreiben. Sonst kann die Logdatei sehr groß werden.
Dafür gibt es rotierende File Handler:
import logging
from logging.handlers import RotatingFileHandler
handler = RotatingFileHandler(
"dungeon.log",
maxBytes=1_000_000,
backupCount=3,
encoding="utf-8",
)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
handlers=[handler],
)
Wenn dungeon.log ungefähr 1_000_000 Bytes erreicht, wird rotiert.
backupCount=3 sorgt dafür, dass einige ältere Dateien erhalten bleiben.
Für unseren Lern-Dungeon ist das nicht notwendig. Für Dienste, Bots und Cronjobs ist es aber ein wichtiges Muster.
Datum und Uhrzeit formatieren
Das Feld %(asctime)s erzeugt einen Zeitstempel.
Mit datefmt kannst Du seine Darstellung anpassen:
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
Eine mögliche Ausgabe:
2026-07-29 14:30:00 INFO __main__: Spiel gestartet
Ohne datefmt verwendet Logging eine eigene Standarddarstellung mit
Millisekunden.
basicConfig(...) wirkt nur einmal
logging.basicConfig(...) richtet den Root-Logger ein, wenn noch keine Handler
vorhanden sind.
Das bedeutet: Der erste wirksame Aufruf gewinnt.
Diese Situation kann verwirren:
logging.basicConfig(level=logging.WARNING)
logging.basicConfig(level=logging.DEBUG)
logging.debug("Diese Meldung erscheint nicht.")
Der zweite Aufruf ändert normalerweise nichts mehr.
Seit Python 3.8 gibt es die Option force=True:
logging.basicConfig(
level=logging.DEBUG,
force=True,
)
Damit werden vorhandene Handler entfernt und die Konfiguration neu gesetzt.
force=True ist nützlich in kleinen Skripten, Tests oder interaktiven Sessions.
In größeren Anwendungen solltest Du Logging trotzdem gezielt und zentral
konfigurieren.
In Bibliotheken nicht konfigurieren
Eine wichtige Regel:
Bibliotheken konfigurieren Logging nicht.
Eine Bibliothek sollte nur einen Logger holen und Nachrichten schreiben:
import logging
logger = logging.getLogger(__name__)
def speichern(name):
logger.info("Speichere Spielstand für %s", name)
Sie sollte aber nicht selbst basicConfig(...) aufrufen.
Warum?
Die Anwendung, die die Bibliothek benutzt, entscheidet:
- ob überhaupt geloggt wird,
- ab welchem Level geloggt wird,
- ob Logs in die Konsole, Datei oder ein anderes System gehen,
- welches Format verwendet wird.
Wenn eine Bibliothek ungefragt Logging konfiguriert, überschreibt oder stört sie die Entscheidung der Anwendung.
Für eigene Skripte und Anwendungen ist basicConfig(...) in Ordnung. Für
wiederverwendbare Module und Bibliotheken nicht.
Logging im Dungeon
Wir ergänzen unseren Dungeon um Logging.
Am Anfang der Datei:
import logging
from pathlib import Path
LOGDATEI = Path("dungeon.log")
logger = logging.getLogger(__name__)
Dann eine zentrale Konfigurationsfunktion:
def konfiguriere_logging():
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
handlers=[
logging.StreamHandler(),
logging.FileHandler(
LOGDATEI,
encoding="utf-8",
),
],
)
Diese Funktion rufen wir einmal in main() auf:
def main():
konfiguriere_logging()
logger.info("Dungeon gestartet")
...
Beim Beenden:
if verb == "ende":
logger.info("Dungeon beendet: spieler=%s ort=%s", spieler.name, ort)
print("Du verlässt das Verlies. Bis zum nächsten Mal.")
break
Beim Speichern:
if verb == "speichern":
speichere_spielstand(
spieler=spieler,
ort=ort,
raeume=raeume,
besuchte_raeume=besuchte_raeume,
)
logger.info(
"Spielstand gespeichert: spieler=%s ort=%s",
spieler.name,
ort,
)
print("Spielstand gespeichert.")
continue
Beim Laden:
if verb == "laden":
ort, besuchte_raeume = lade_spielstand(
spieler=spieler,
raeume=raeume,
)
raum_anzeigen = True
logger.info(
"Spielstand geladen: spieler=%s ort=%s",
spieler.name,
ort,
)
print("Spielstand geladen.")
continue
Und im Fehlerfall:
try:
...
except DungeonError as fehler:
logger.warning("Benutzerfehler: %s", fehler)
print(fehler)
Damit landet eine erwartbare falsche Eingabe im Log, ohne den Benutzer mit einem Traceback zu belasten.
Für unerwartete Fehler wäre ein vollständiger Traceback sinnvoller. In unserem
Game-Loop fangen wir aber bewusst nur DungeonError. Echte Bugs bleiben sichtbar
und brechen weiterhin mit Traceback ab.
Logging in der Speicherfunktion
Auch in der Speicherlogik können Logs hilfreich sein.
def speichere_spielstand(spieler, ort, raeume, besuchte_raeume):
logger.debug(
"Erstelle Spielstand: spieler=%s ort=%s inventar=%s",
spieler.name,
ort,
len(spieler.inventar),
)
daten = erstelle_spielstand(
spieler=spieler,
ort=ort,
raeume=raeume,
besuchte_raeume=besuchte_raeume,
)
try:
with SPEICHERDATEI.open("w", encoding="utf-8") as datei:
json.dump(daten, datei, ensure_ascii=False, indent=2)
datei.write("\n")
except OSError as fehler:
logger.exception("Schreiben des Spielstands fehlgeschlagen")
raise SpielstandError(
f"Der Spielstand konnte nicht gespeichert werden: {fehler}"
) from fehler
Bei normalem INFO-Level erscheint die DEBUG-Meldung nicht.
Stellst Du auf DEBUG, bekommst Du zusätzliche Details.
logging.basicConfig(level=logging.DEBUG)
Das ist besonders nützlich, wenn ein Fehler nur in bestimmten Situationen auftritt.
Logging ersetzt keine Benutzeroberfläche
Ein wichtiger Unterschied:
print("Spielstand gespeichert.")
ist eine Meldung an den Benutzer.
logger.info("Spielstand gespeichert: spieler=%s ort=%s", spieler.name, ort)
ist eine Meldung an Entwickler, Betreiber oder das spätere Debugging.
Beides kann im selben Programm vorkommen.
Ein Benutzer soll nicht jede technische Logzeile sehen. Umgekehrt reicht eine freundliche Konsolenausgabe nicht aus, um später einen Fehler zu untersuchen.
Deshalb gilt:
print(...)oder UI-Ausgabe für direkte Benutzerkommunikation.loggingfür Diagnose, Betrieb und Nachvollziehbarkeit.
stack_info und stacklevel
Neben Exception-Tracebacks kann Logging auch Informationen über den aktuellen Aufrufpfad ausgeben.
Mit stack_info=True erhältst Du Stack-Informationen, auch wenn keine Exception
aufgetreten ist:
logger.debug("Aktueller Pfad durch das Programm", stack_info=True)
Das brauchst Du selten, kann aber bei schwer nachvollziehbaren Aufrufen helfen.
stacklevel ist nützlich, wenn Du eigene Logging-Hilfsfunktionen schreibst:
def logge_warnung(nachricht):
logger.warning(nachricht, stacklevel=2)
Dadurch zeigt die Logmeldung auf den Aufrufer der Hilfsfunktion statt auf die Hilfsfunktion selbst.
Für den Einstieg sind beide Optionen nicht notwendig. Gut zu kennen sind sie trotzdem, weil sie in größeren Projekten auftauchen können.
Logging-Konfiguration über Datei
Für größere Anwendungen wird Logging häufig nicht direkt mit basicConfig(...)
konfiguriert, sondern über eine Konfigurationsdatei oder ein Dictionary.
Das Standardmodul bietet dafür unter anderem:
logging.config.dictConfig(...)
Damit lassen sich mehrere Logger, Handler und Formatter zentral beschreiben.
Für unseren Lernstand ist basicConfig(...) übersichtlicher. Sobald ein Projekt
mehrere unterschiedliche Logdateien, JSON-Logs oder externe Logsysteme benötigt,
lohnt sich ein Blick auf logging.config.
Welche Meldung gehört auf welches Level?
Die Level-Wahl ist nicht immer eindeutig. Diese grobe Orientierung hilft:
DEBUG
Sehr detaillierte Informationen für die Fehlersuche:
logger.debug("Geladene Rohdaten: %r", daten)
logger.debug("Befehl zerlegt: verb=%s argument=%s", verb, argument)
Im normalen Betrieb meist deaktiviert.
INFO
Normale wichtige Ereignisse:
logger.info("Dungeon gestartet")
logger.info("Spielstand gespeichert")
logger.info("Spielstand geladen")
Gut für die Frage: Was hat das Programm regulär getan?
WARNING
Unerwartete, aber verkraftbare Situationen:
logger.warning("Kein Spielstand gefunden, neues Spiel wird gestartet")
logger.warning("Unbekannter Befehl: %s", verb)
Das Programm kann weiterlaufen, aber die Situation ist auffällig.
ERROR
Eine Operation ist fehlgeschlagen:
logger.error("Spielstand konnte nicht gespeichert werden")
Das Programm läuft vielleicht weiter, aber die konkrete Aktion ist gescheitert.
Mit Traceback im except-Block:
logger.exception("Spielstand konnte nicht gespeichert werden")
CRITICAL
Ein schwerer Fehler, bei dem das Programm wahrscheinlich nicht sinnvoll weiterarbeiten kann:
logger.critical("Konfiguration fehlt, Programm wird beendet")
Dieses Level sollte selten sein.
Stolperfallen
-
Logging nur als besseres
print(...)verwenden: Logging ist nicht nur Ausgabe, sondern strukturierte Diagnose mit Levels, Loggern, Handlern und Formatierung. -
In jedem Modul
basicConfig(...)aufrufen: Konfiguriere Logging einmal zentral in der Anwendung. -
In Bibliotheken Logging konfigurieren: Bibliotheken holen sich nur einen Logger und schreiben Logs. Die Anwendung entscheidet über Ausgabe und Format.
-
Den Root-Logger als Dauerlösung verwenden: Für mehr als kleine Skripte ist
logger = logging.getLogger(__name__)die bessere Gewohnheit. -
f-Strings für Logmeldungen verwenden:
logger.debug(f"{wert}")baut den String sofort. Verwende besserlogger.debug("%s", wert). -
logger.exception(...)außerhalb einesexcept-Blocks verwenden: Die Methode ist für den aktuellen Exception-Kontext gedacht. -
Erwartete Benutzerfehler immer mit Traceback loggen: Das erzeugt unnötigen Lärm. Nicht jeder ungültige Befehl ist ein technischer Fehler.
-
Zu viele Meldungen auf
ERRORsetzen: Wenn alles ein Fehler ist, ist am Ende nichts mehr priorisiert. -
logging.warn(...)verwenden: Die alte Methode ist veraltet. Verwendelogging.warning(...)beziehungsweiselogger.warning(...). -
Geheimnisse loggen: Passwörter, Tokens, Session-Cookies, personenbezogene Daten oder private Inhalte gehören nicht unbedacht ins Log.
-
Unbegrenzte Logdateien erzeugen: Für dauerhaft laufende Programme solltest Du Rotation oder ein externes Logsystem verwenden.
-
Logs mit Benutzerkommunikation verwechseln: Eine Logmeldung ersetzt keine verständliche Ausgabe für den Benutzer.
-
basicConfig(...)mehrfach erwarten: Ohneforce=Truewirkt ein späterer Aufruf oft nicht mehr, wenn bereits Handler eingerichtet sind.
Übungen
1. Logging einrichten
Richte Logging so ein, dass INFO und höher mit Zeitstempel, Level und Logger-
Name ausgegeben werden.
Lösung
import logging
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
)
logger = logging.getLogger(__name__)
logger.info("Programm gestartet")
2. Einen Modul-Logger verwenden
Schreibe eine Funktion speichern(name), die eine Logmeldung ausgibt, ohne
print(...) zu verwenden.
Lösung
import logging
logger = logging.getLogger(__name__)
def speichern(name):
logger.info("Speichere Spielstand für %s", name)
3. Eine Exception mit Traceback loggen
Fange einen ValueError ab und logge den vollständigen Traceback.
Lösung
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
try:
zahl = int("viel")
except ValueError:
logger.exception("Umwandlung in int fehlgeschlagen")
4. In eine Datei loggen
Konfiguriere Logging so, dass Meldungen ab INFO in die Datei app.log
geschrieben werden.
Lösung
import logging
logging.basicConfig(
filename="app.log",
encoding="utf-8",
level=logging.INFO,
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
)
logger = logging.getLogger(__name__)
logger.info("Datei-Logging aktiv")
Vertiefung
Wenn Logs zeigen, dass etwas schiefgeht, Du aber den laufenden Code genauer untersuchen möchtest:
Debuggen mit pdbgeplant
Wenn Du die Fehlerbehandlung aus der Python-Serie noch einmal nachlesen möchtest:
Python lernen, Teil 8: Wenn's schiefgeht
0 Kommentare
Noch keine Kommentare. Sei der/die Erste!
Anmelden um einen Kommentar zu hinterlassen.