Python Tutorial für Data Science: Grundlagen: Fehlerbehandlung & Logging

Beim Programmieren in Python — und besonders in Data-Science-Projekten — laufen wir früher oder später auf Fehler.
Zum Beispiel:

  • Eine Datei ist nicht vorhanden.
  • Ein Wert ist vom falschen Typ (z. B. ein String statt einer Zahl).
  • Ein Modell-Training bricht ab, weil Speicher fehlt.

Damit der Code nicht sofort abstürzt und man versteht, warum etwas schiefgeht, gibt es in Python Fehlerbehandlung und Logging.
Beides sind zentrale Werkzeuge, um stabile und nachvollziehbare Programme zu schreiben.

Fehler (Exceptions) in Python

In Python nennt man Fehler Exceptions (engl. für „Ausnahmen“).
Eine Exception bedeutet: „Etwas Unvorhergesehenes ist passiert, und der normale Ablauf kann nicht fortgesetzt werden.“

Beispiele für eingebaute Exceptions:

  • ValueError → wenn ein Wert nicht passt (z. B. int("abc"))
  • TypeError → wenn der Datentyp nicht stimmt (z. B. len(5))
  • FileNotFoundError → wenn eine Datei nicht existiert
  • ZeroDivisionError → bei Division durch null

Fehler abfangen mit try und except

Man kann Fehler gezielt abfangen, um kontrolliert zu reagieren.

try:
    zahl = int("abc")  # das löst einen ValueError aus
except ValueError as e:
    print("Konvertierung fehlgeschlagen:", e)

Erklärung:

  • try: Python versucht, den Code darin auszuführen.
  • except: Falls ein bestimmter Fehler auftritt, wird dieser Teil ausgeführt.
  • as e: Speichert die Fehlermeldung in einer Variablen, sodass man sie weiterverwenden kann.

So bleibt das Programm lauffähig, auch wenn ein Teil fehlschlägt.

Mehrere Fehler abfangen

Man kann verschiedene Fehlerarten unterschiedlich behandeln:

try:
    with open("daten.csv") as f:
        inhalt = f.read()
except FileNotFoundError:
    print("Datei nicht gefunden – bitte Pfad prüfen.")
except PermissionError:
    print("Keine Berechtigung zum Lesen der Datei.")

Fehler weitergeben (raise)

Manchmal möchte man Fehler bewusst weiterwerfen, zum Beispiel in einer Funktion:

def teile(a, b):
    if b == 0:
        raise ValueError("Division durch 0 nicht erlaubt")
    return a / b

Hier verhindert man, dass ein ungültiger Wert einfach stillschweigend verarbeitet wird.

Aufräumen mit finally

Wenn man z. B. Dateien oder Datenbankverbindungen nutzt, muss man sicherstellen, dass Ressourcen wieder freigegeben werden.
Dafür gibt es den Block finally:

try:
    f = open("daten.csv")
    # ... etwas mit der Datei tun ...
finally:
    f.close()  # wird garantiert ausgeführt

finally läuft immer, egal ob ein Fehler aufgetreten ist oder nicht.

Logging – Was ist das?

Logging bedeutet: Informationen über den Programmablauf (und auch Fehler) systematisch protokollieren.
Das ist viel besser als print(), weil:

  • Logs haben Level (z. B. INFO, WARNING, ERROR).
  • Logs können in Dateien geschrieben werden.
  • Man kann später nachverfolgen, wann und wo etwas passiert ist.

Das logging-Modul

Python hat ein eingebautes Modul namens logging.

Ein einfaches Beispiel:

import logging

logging.basicConfig(level=logging.INFO)

logging.info("Starte das Programm")
logging.warning("Dies ist eine Warnung")
logging.error("Ein Fehler ist aufgetreten")

Erklärung:

  • basicConfig(level=...) legt die minimale Wichtigkeit fest, ab der Logs angezeigt werden.
  • info, warning, error sind Methoden mit verschiedenen Log-Leveln.

Wichtige Log-Level

  • DEBUG: sehr detaillierte Infos (z. B. Zwischenergebnisse, nur für Entwickler:innen nützlich)
  • INFO: normale Statusmeldungen (z. B. „Training gestartet“)
  • WARNING: Hinweis, dass etwas unerwartet ist, aber nicht kritisch
  • ERROR: ein Fehler ist passiert, der Code kann evtl. nicht weiterlaufen
  • CRITICAL: sehr schwerer Fehler, Programm muss beendet werden

Logs in eine Datei schreiben

Sehr praktisch in Data-Science-Projekten, wenn man lange Pipelines oder Trainings laufen lässt:

import logging

logging.basicConfig(
    filename="pipeline.log",
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s"
)

logging.info("Pipeline gestartet")
logging.error("Ein Fehler in Schritt 3")

Hier wird alles in die Datei pipeline.log geschrieben, mit Zeitstempel, Log-Level und Nachricht.

Kombination Fehlerbehandlung + Logging

Häufig nutzt man beides zusammen:

import logging

logging.basicConfig(level=logging.INFO)

try:
    daten = [1, 2, 3]
    wert = daten[5]  # IndexError
except IndexError as e:
    logging.error("Fehler beim Zugriff auf Liste: %s", e)

So wird der Fehler nicht nur abgefangen, sondern auch protokolliert.

Best Practices

  • Nicht alles abfangen: Nur Fehler behandeln, die man sinnvoll verarbeiten kann.
  • Logs statt Prints: Logs sind strukturierter und langfristig nützlicher.
  • Kombinieren: Fehler abfangen, sinnvolle Fehlermeldung loggen, Programm stabil halten.
  • Im Data-Science-Kontext:
    • Logs für Datenqualität (z. B. „10% Missing Values gefunden“)
    • Fehlerbehandlung für Inputdaten (z. B. falsches Dateiformat)