Fehler sind, wie Python dir sagt, was passiert ist
Jeder Python-Fehler ist ein Objekt mit einem Typ, einer Nachricht und einem Traceback — der Kette von Aufrufen, die dahin führte. Einen gut zu lesen, ist die größte einzelne Debugging-Fertigkeit, die du dir aneignen kannst. Diese Seite ist eine Tour durch die Fehler, denen du tatsächlich begegnest, und die Gewohnheiten, die sie schnell beheben.
Für einen tieferen Blick auf die Mechanik von try/except und eigenes Werfen siehe die Ausnahmen-Seite. Diese Seite handelt von den konkreten Fehlern und wie du sie liest.
Einen Traceback lesen
Führ etwas Kaputtes aus:
def divide(a, b):
return a / b
def report(values):
for v in values:
print(divide(10, v))
report([5, 2, 0])
Python druckt etwas wie:
Traceback (most recent call last):
File "script.py", line 8, in <module>
report([5, 2, 0])
File "script.py", line 6, in report
print(divide(10, v))
File "script.py", line 2, in divide
return a / b
ZeroDivisionError: division by zero
Lies das von unten nach oben:
ZeroDivisionError: division by zero— der Ausnahmetyp und die Nachricht. Das ist was schief ging.return a / bbeidivide, Zeile 2 — die Zeile, die tatsächlich geworfen hat.print(divide(10, v))beireport, Zeile 6 — der Aufruf, der es auslöste.report([5, 2, 0])auf Modul-Ebene, Zeile 8 — wo es begann.
Der unterste Frame ist fast immer, wo die Lösung hingehört. Wirft eine Bibliothek tief in ihrem Inneren einen Fehler, wander den Traceback hoch zum ersten Frame in deinem Code — das ist der Aufruf, an dem du schlechte Eingabe übergeben hast.
Die Fehler, denen du am häufigsten begegnest
NameError
„Name 'mesage' is not defined.“ Verursacht durch Tippfehler oder Nutzung einer Variable, bevor sie zugewiesen wurde. Pythons Fehlermeldung nennt in neueren Versionen oft einen wahrscheinlichen Ersatz („Did you mean 'message'?“).
Lösung: Rechtschreibung und Gültigkeitsbereich prüfen. Existiert der Name nur innerhalb einer Funktion, kannst du ihn von außen nicht lesen.
TypeError
„Can only concatenate str (not 'int') to str.“ Falscher Typ für die Operation. Klassiker: String zu Zahl addieren, etwas aufrufen, was nicht aufrufbar ist, einer Funktion die falsche Anzahl Argumente übergeben.
Lösung: Typen explizit umwandeln (str(30), int("30")) oder prüfen, was du wirklich übergibst. Ein f-String liest sich meist besser als +-Verkettung über Typen: f"age: {30}".
ValueError
„Invalid literal for int() with base 10: 'hello'.“ Der Typ stimmt — int() akzeptiert einen String —, aber der Wert passt nicht. Häufig bei int(), float(), datetime-Parsing und Funktionen mit beschränkten Argumenten.
Lösung: vor dem Umwandeln validieren oder den Fehler fangen:
KeyError
„KeyError: 'charlie'.“ Der Schlüssel ist nicht im Dict. Drei idiomatische Lösungen, je nach Absicht:
Für ein Dict, in dem fehlende Schlüssel automatisch initialisiert werden sollen, lohnt sich collections.defaultdict.
IndexError
„List index out of range.“ Du hast eine Position angefragt, die die Sequenz nicht hat.
Lösung: mit einer Längenprüfung absichern, -1 für das letzte Element nutzen oder Slicing (numbers[5:6] liefert [] statt zu werfen).
AttributeError
„'NoneType' object has no attribute 'upper'.“ Du hast eine Methode auf etwas aufgerufen, das sie nicht hat. Fast immer heißt das, dass eine Variable einen unerwarteten Typ hat — oft None, wenn du einen echten Wert erwartet hast.
Lösung: finde heraus, woher das None kommt. print(type(var)) oder ein Breakpoint direkt vor dem Fehler ist der schnellste Weg. Funktionen, die „manchmal scheitern“, liefern meist None; prüf ihren Rückgabewert, bevor du Methoden darauf aufrufst.
ModuleNotFoundError (und ImportError)
import fastapi
„No module named 'fastapi'.“ Das Paket ist nicht im Python-Interpreter installiert, den dein Skript nutzt. Zwei häufige Ursachen:
- Du hast es wirklich nicht installiert. Führ
python -m pip install fastapiin der richtigen Umgebung aus. - Du hast es installiert, aber in einem anderen Python. Unter macOS ständig, wenn
pipundpythonauf verschiedene Installationen zeigen.
Die verlässliche Lösung: mit demselben Interpreter installieren, mit dem du läufst:
python -m pip install fastapi
Nutzt du eine virtuelle Umgebung (und das solltest du), stell sicher, dass sie vor pip install und python script.py aktiviert ist.
FileNotFoundError
with open("settings.yaml") as f:
config = f.read()
„[Errno 2] No such file or directory: 'settings.yaml'.“ Der Pfad existiert relativ zum aktuellen Ausführungsort nicht.
Lösung: os.getcwd() am Anfang des Skripts drucken, um zu bestätigen, wo Python sucht. Absolute Pfade nutzen oder pathlib.Path(__file__).parent / "settings.yaml", um Pfade am Skript selbst zu verankern.
EOFError
name = input("Name: ")
„EOF when reading a line.“ input() versuchte, von stdin zu lesen, und bekam nichts — entweder war die Eingabe aus einer leeren Quelle gepiped, oder du hast am Prompt Strg-D gedrückt.
Lösung: ist Pipen legitim, wickle den Aufruf ein:
try:
name = input("Name: ")
except EOFError:
name = "anonymous"
Im Browser-Editor dieser Dokumentation simuliert die Laufzeit die Eingabe; dort triffst du das nicht.
IndentationError und SyntaxError
IndentationError: expected an indented block after function definition on line 2
Die sind besonders — sie werden geworfen, bevor dein Programm läuft. Python weigerte sich, die Datei zu parsen.
IndentationError— der Rumpf einesdef,if,forusw. fehlt oder ist versetzt. Die meisten Editoren visualisieren Einrückung; schalte „Show Whitespace“ an, um gemischte Tabs und Leerzeichen zu erkennen.SyntaxError— du hast einen Doppelpunkt vergessen, eine Klammer unpassend gesetzt oder ein Schlüsselwort falsch geschrieben. Neuere Python-Versionen zeigen mit einem Pfeil (^) auf das Problemzeichen.
Lösung: Die Fehlermeldung nennt die Zeile. Geh nachsehen. Ist an dieser Zeile nichts offensichtlich, prüf die Zeile darüber — eine nicht geschlossene Klammer weiter oben zeigt sich oft erst viel später als Syntaxfehler.
RuntimeError
Ein Sammeltopf für „etwas ist zur Laufzeit schief gegangen, das keinen spezifischeren Fehler hat“. RecursionError (Rekursionstiefe überschritten) ist eine häufige Spezialisierung. Bibliothekscode wirft oft RuntimeError, wenn er sich in einem schlechten Zustand befindet.
Lösung: lies die Nachricht; sie ist meist beschreibend. Ist Rekursion die Ursache, wandle in eine iterative Schleife um oder erhöhe in seltenen Fällen mit sys.setrecursionlimit.
print-Debugging
Bevor du zu einem echten Debugger greifst, fängt print() — oder besser die f"{var=}"-Form — die meisten Bugs:
f"{var=}" druckt Ausdruckstext und Wert, sodass du den Namen im Format-String nicht wiederholen musst. Führ das Skript aus, überflieg die Ausgabe, finde die Zeile, an der ein Wert falsch wurde. Die meisten „mysteriösen“ Bugs werden mit drei oder vier gut platzierten Prints offensichtlich.
Räum die Prints vor dem Commit auf. logging.debug(...) ist für produktiven Code angenehmer als print — du kannst Debug-Logging an- und ausschalten, ohne Zeilen zu bearbeiten.
breakpoint() und pdb
Wenn print nicht reicht, versetzt dich breakpoint() an dieser Stelle in Pythons interaktiven Debugger:
def discount(price, percent):
breakpoint()
return price * (1 - percent / 100)
discount(100, 20)
Führ das Skript in einem echten Terminal aus. Du landest an einem (Pdb)-Prompt. Ein paar Befehle zum Merken:
p variable— Variable drucken.n— zur nächsten Zeile gehen.s— in einen Funktionsaufruf hineinsteigen.c— weiterlaufen bis zum nächsten Breakpoint oder Ende.q— beenden.l— Quelltext um die aktuelle Zeile anzeigen.
IDE-Debugger (VS Code, PyCharm) wickeln dasselbe Protokoll in eine GUI — Breakpoints im Rand, Sidebar mit Variablen. Nimm, was sich reibungsärmer anfühlt.
Gewohnheiten, die Fehler reduzieren
- Nutz aussagekräftige Variablennamen. Die Hälfte des
TypeError- undAttributeError-Lärms verschwindet, wenn du nicht vergisst, was in einer Variablen steckt. - Validier Eingaben an der Grenze. Parse und prüfe Nutzer-/Dateiinhalte einmal, am Kopf der Funktion. Der Rest des Codes kann den Werten dann vertrauen.
- Schreit laut, nicht leise. Ein nacktes
except Exception: passverbirgt genau die Fehler, die du sehen musst. Fang konkrete Ausnahmen, behandle sie bewusst und lass den Rest durch. - Lies das Ende des Tracebacks zuerst. Jede Minute, die du ins Traceback-Lesen steckst, zahlt sich hundertfach aus.
Die meisten Fehler sind keine Rätsel — sie sind Einzeilen-Tippfehler oder Falscher-Typ-Fehler mit klarer Nachricht. Vertrau der Fehlermeldung; sie hat meist recht.
Du hast es geschafft
Das ist das Ende der Referenz. Du bist von „was ist Python?“ durch Variablen, Kontrollfluss, Sammlungen, Funktionen, Klassen, Iteration, echte Daten und Fehler gegangen. Von hier aus sind die nächsten Schritte projektförmig: wähl etwas, das du bauen willst, und arbeite dich rückwärts zu den Bausteinen vor, die du tiefer lernen musst. Diese Seiten sind noch hier, wenn du mit einer konkreten Frage zurückkommst.
Häufig gestellte Fragen
Was ist ein KeyError in Python?
KeyError wird geworfen, wenn du einen Dict-Schlüssel nachschlägst, der nicht existiert. users["missing"] wirft KeyError: 'missing'. Sichere Alternativen: users.get("missing", default), users.get("missing") (liefert None) oder eine ausdrückliche if key in users:-Prüfung.
Was ist ein EOFError in Python?
EOFError (end-of-file) wird geworfen, wenn input() nichts lesen kann, weil der Eingabestream geschlossen ist. Du siehst ihn meist, wenn ein Skript, das input() nutzt, ohne Daten gepiped wird, oder wenn du im interaktiven Prompt Strg-D drückst. Schütz dich mit try/except EOFError, wenn dein Skript gepipete Eingabe verarbeiten soll.
Was ist ein ModuleNotFoundError?
ModuleNotFoundError heißt, dass import X kein Modul namens X fand. Entweder ist das Paket nicht installiert (pip install X), oder es ist in einem anderen Python installiert als dem, der deinen Code ausführt (häufig bei mehreren Python-Versionen). python -m pip install X löst den zweiten Fall, weil derselbe Interpreter genutzt wird.
Wie lese ich einen Python-Traceback?
Lies ihn von unten nach oben. Die letzte Zeile ist der Ausnahmetyp und die Nachricht — das konkrete Problem. Die Zeilen darüber zeigen den Aufrufstapel, der dorthin führte, wobei dein eigener Code meist näher unten steht. Spring zur Datei + Zeile im untersten Frame, der dir gehört; dort wohnt die Lösung.