Wenn Code bricht

Eine Anleitung für den Moment, in dem das Programm nicht das tut, was du wolltest — also fast immer.

Grundlagen 13 min Einsteiger 26. April 2026

In dem Moment, in dem dein Code zum ersten Mal eine Wand aus rotem Text erzeugt, ist dein erster Instinkt: Panik. Aber dieser rote Text, der Traceback, ist eigentlich das Hilfreichste, was Python dir geben kann. Er sagt dir genau, was schiefgelaufen ist, genau wo und genau warum.

Die echte Gefahr lauert nicht, wenn Python dich anschreit, sondern wenn Python schweigt und deine Ergebnisse leise, unauffällig falsch sind. Dieser Artikel bringt dir bei, Python-Fehler in drei Typen einzuteilen, Tracebacks wie ein Detektiv zu lesen und Sicherheitsnetze zu schreiben, die dein Programm am Laufen halten.

Drei Arten von Fehlern

Fehlerarten in Python

AnalogieDefinition
Stell dir ein Kochrezept vor. Ein Syntaxfehler ist ein Rezept mit einem Wort, das der Koch nicht lesen kann: "Gib 200g Sltz hinzu." Der Koch hört sofort auf, die Anweisung ist unverständlich. Ein Laufzeitfehler ist eine Anweisung, die klar klingt, aber in der Praxis scheitert: "Teile den Teig in Portionen basierend auf der Anzahl der Eier." Bei null Eiern steckt der Koch fest, Division durch Null. Ein Logikfehler ist ein Rezept, das perfekt lesbar und ausführbar ist, aber falsch: "Gib 200 Kilogramm Salz hinzu." Der Koch folgt der Anweisung, und das Ergebnis ist ungenießbar, aber niemand hat dem Koch gesagt, dass etwas nicht stimmt.

Die Rezept-Analogie bricht an zwei Stellen: Ein echter Koch würde "200 Kilogramm Salz" hinterfragen, er hat gesunden Menschenverstand. Python hat keinen Menschenverstand und führt jede logisch gültige Anweisung aus. Außerdem kann ein Koch das Ergebnis probieren, Code dagegen braucht systematische Tests.

Syntaxfehler Stoppt vor der Ausführung. Fehlende Klammern, Doppelpunkte, falsche Einrückung.
Laufzeitfehler Stürzt während der Ausführung ab. Erzeugt einen Traceback mit Fehlermeldung.
Logikfehler Läuft ohne Warnung durch. Liefert falsche Ergebnisse. Am gefährlichsten.

Drei Fehler, ein Programm

Der gleiche Temperaturrechner kann auf alle drei Arten scheitern:

# Syntaxfehler: fehlende Klammer
celsius = (fahrenheit - 32 * 5 / 9
# SyntaxError: Python weigert sich zu starten

Python kann den Code gar nicht ausführen, die Klammer fehlt.

# Laufzeitfehler: Nutzer gibt Text statt Zahl ein
eingabe = input("Temperatur: ")
celsius = (int(eingabe) - 32) * 5 / 9
# ValueError wenn Nutzer "warm" statt einer Zahl tippt

Der Code ist syntaktisch korrekt, stürzt aber ab, wenn die Eingabe keine Zahl ist.

# Logikfehler: + statt - (läuft, aber falsche Ergebnisse)
celsius = (fahrenheit + 32) * 5 / 9
# Kein Fehler, kein Absturz, aber das Ergebnis ist falsch!

Python beschwert sich nicht, weil der Code syntaktisch korrekt und ausführbar ist. Aber die Formel ist falsch (+ statt -), und die Ergebnisse stimmen nicht.

Kein Fehler heißt nicht kein Problem

Der gefährlichste Irrglaube: "Mein Code läuft ohne Fehlermeldung, also ist er korrekt." Logikfehler erzeugen keine Meldung. Dein Code läuft durch und liefert Ergebnisse, nur sind die Ergebnisse falsch. Der einzige Schutz: Teste mit bekannten Eingaben und prüfe, ob die erwarteten Ergebnisse herauskommen.

Den Traceback lesen: Deine Fehlerkarte

Traceback

AnalogieDefinition
Ein Traceback ist wie ein Unfallbericht. Ganz unten steht der Unfall selbst: "Fahrzeug ist an Kreuzung X gegen eine Mauer gefahren" (Fehlertyp und Meldung). Der Abschnitt darüber beschreibt die unmittelbaren Umstände: "Fahrzeug fuhr mit 80 km/h auf der Hauptstraße, Zeile 47" (die fehlerhafte Codezeile). Die Abschnitte weiter oben zeichnen die Route nach: "Fahrzeug verließ das Parkhaus um 8:00 Uhr, bog auf die Autobahn ab" (die Kette der Funktionsaufrufe).

Die Analogie bricht an einer wichtigen Stelle: Ein echter Unfallbericht ist chronologisch von oben nach unten aufgebaut. Pythons Traceback zeigt den neuesten Aufruf ganz unten ("most recent call last"). Deshalb muss man lernen, von unten nach oben zu lesen.

Traceback lesen: 4 Schritte

1
Lies die letzte Zeile: Fehlertyp und Fehlermeldung (z.B. ValueError: invalid literal)
2
Lies die Zeile darüber: Welche Codezeile hat den Fehler ausgelöst?
3
Gehe die Aufrufkette nach oben: Welche Funktion hat welche aufgerufen?
4
Finde die Ursache: Welche Funktion hat den problematischen Wert übergeben?

Ein Traceback in der Praxis

def get_age():
    return int(input("Dein Alter: "))    # Nutzer tippt "zwanzig"

def greet_user():
    alter = get_age()
    print(f"Du bist {alter} Jahre alt.")

greet_user()
Traceback (most recent call last):
  File "app.py", line 7, in <module>       # 3. Programm startete hier
    greet_user()
  File "app.py", line 5, in greet_user     # 2. greet_user rief get_age auf
    alter = get_age()
  File "app.py", line 2, in get_age        # 1. get_age stürzte HIER ab
    return int(input("Dein Alter: "))
ValueError: invalid literal for int() with base 10: 'zwanzig'

Lies von unten: ValueError sagt dir den Fehlertyp. Die Zeile darüber zeigt, dass int(input(...)) in get_age() abgestürzt ist. Die Zeilen darüber zeigen den Weg: greet_user() hat get_age() aufgerufen, und das Hauptprogramm hat greet_user() aufgerufen.

Nicht einfach drauflos ändern

Ein häufiger Fehler: Den Traceback ignorieren und den Code auf gut Glück ändern. Der Traceback sagt dir genau, wo und was schiefgelaufen ist. Lies ihn von unten nach oben, und du sparst dir stundenlanges Raten.

Fehlerbehandlung: Sicherheitsnetze schreiben

Exception Handling (try/except)

AnalogieDefinition
Stell dir einen Fallschirmspringer vor. Der Sprung selbst ist der try-Block, der normale Programmablauf. Wenn der Hauptfallschirm nicht öffnet (ein Fehler auftritt), zieht der Springer den Reservefallschirm, der except-Block fängt das spezifische Problem ab. Der finally-Block ist die Landung: Sie passiert unabhängig davon, welcher Fallschirm benutzt wurde, und umfasst Aufräumarbeiten.

Die Analogie bricht, weil ein Springer nur einen Reservefallschirm hat, Python aber mehrere except-Blöcke für verschiedene Fehlertypen erlaubt, wie separate Reserveschirme für verschiedene Ausfallarten.

Der try/except-Ablauf

1
try-Block wird ausgeführt: der "riskante" Code läuft normal
2
Exception tritt auf: Python sucht einen passenden except-Block
3
except-Block reagiert: Fehlermeldung anzeigen, erneut versuchen oder Standardwert verwenden

Praxis: Robuste Eingabe

def get_number(prompt):
    while True:
        try:
            return float(input(prompt))
        except ValueError:
            print("Das ist keine gültige Zahl. Versuch es nochmal.")

temperatur = get_number("Temperatur in Fahrenheit: ")
celsius = (temperatur - 32) * 5 / 9
print(f"{temperatur}°F = {celsius:.1f}°C")

Die Funktion fragt so lange nach einer Zahl, bis der Nutzer eine gültige eingibt. Der try-Block versucht die Konvertierung, der except-Block fängt den ValueError ab und gibt eine freundliche Meldung aus.

except: pass ist gefährlich

Das gefährlichste Muster in Python: except: pass. Es verschluckt alle Fehler, auch echte Bugs wie Tippfehler in Variablennamen, und macht sie unsichtbar.

# GEFÄHRLICH: verschluckt ALLE Fehler
try:
    ergebnis = berechne_preis(artikel)
except:
    pass    # Stille. Kein Fehler sichtbar.

# RICHTIG: nur den erwarteten Fehler fangen
try:
    ergebnis = berechne_preis(artikel)
except ValueError:
    print("Ungültiger Preis, bitte prüfen.")

Ein bare except: pass fängt alles, auch NameError (Tippfehler), TypeError (falsche Argumente) und sogar KeyboardInterrupt (Ctrl+C). Du wirst nie erfahren, dass dein Code einen Bug hat.

ValueError int("hallo") — falscher Wert für den Typ
TypeError "5" + 3 — falscher Typ für die Operation
FileNotFoundError open("missing.csv") — Datei existiert nicht
KeyError data["key"] — Schlüssel im Dictionary nicht vorhanden
IndexError liste[10] bei einer 3-Element-Liste — Index außerhalb des Bereichs
ZeroDivisionError 100 / 0 — Division durch Null

print()-Debugging: Füge print()-Anweisungen ein, um Variablenwerte an verschiedenen Stellen im Code zu überprüfen. So siehst du Schritt für Schritt, wo die Werte von dem abweichen, was du erwartest.

assert-Anweisungen: Schreibe assert ergebnis > 0, "Ergebnis sollte positiv sein" in deinen Code. Wenn die Bedingung nicht erfüllt ist, stürzt Python absichtlich ab und zeigt dir die Stelle. So machst du stille Logikfehler laut.

Rubber-Duck-Debugging: Erkläre deinen Code Zeile für Zeile einem unbelebten Gegenstand (einer Gummiente, einer Tasse, einem Kuscheltier). Der Zwang, jeden Schritt in Worte zu fassen, zwingt dich, über jeden Schritt nachzudenken, und oft entdeckst du dabei den Fehler.

Interaktiv: Was ist mein Fehler?

Beantworte die Fragen im Diagnosebaum, um herauszufinden welcher Fehlertyp vorliegt und welche Debugging-Strategie am besten hilft. Achte darauf, wie die drei Fehlerarten zu unterschiedlichen Lösungswegen führen.

?

Was passiert wenn du deinen Code ausführst?

Das Wichtigste auf einen Blick

  1. Python-Fehler kommen in drei Arten: Syntaxfehler (Code nicht lesbar, vor der Ausführung abgefangen), Laufzeitfehler (Code stürzt ab, erzeugt einen Traceback) und Logikfehler (Code läuft, aber liefert falsche Ergebnisse, am gefährlichsten weil stumm).
  2. Ein Traceback wird von unten nach oben gelesen: Die letzte Zeile nennt den Fehlertyp, die Zeile darüber zeigt den fehlerhaften Code, die Zeilen darüber zeichnen die Aufrufkette nach.
  3. try/except-Blöcke fangen vorhersehbare Fehler ab und reagieren, statt abzustürzen. Fange immer spezifische Exceptions wie ValueError, niemals bare except:.
  4. except: pass ist das gefährlichste Muster in Python. Es verschluckt alle Fehler, auch echte Bugs, und macht sie unsichtbar und unmöglich zu debuggen.
  5. "Keine Fehlermeldung" heißt nicht "kein Fehler". Logikfehler erzeugen korrekt aussehende Ausgaben, die subtil falsch sind. Teste immer mit bekannten Eingaben und erwarteten Ergebnissen.

Quiz: Debugging

Frage 1 / 4
Noch offen

Welcher Fehlertyp läuft ohne Fehlermeldung durch, liefert aber falsche Ergebnisse?

Wählen Sie eine Antwort
Auflösung: 1) C · 2) B · 3) B · 4) B

Checkpoint: Hast du alles verstanden?

  • Dein Code läuft ohne Fehlermeldung, gibt aber 0 statt 100 aus. Was für ein Fehlertyp ist das, und warum ist er besonders gefährlich?
  • Du siehst einen Traceback, dessen letzte Zeile "KeyError: 'name'" lautet. Wo schaust du zuerst hin, und was verraten dir die Zeilen darüber?
  • Schreibe Code, der den Nutzer nach einer Zahl fragt und so lange nachfragt, bis eine gültige Eingabe kommt. Warum ist except: pass hier keine gute Lösung?