Layer 8Ehrlicher Tech-Support
SoftwareSchweregrad: LästigRecursionError

Python: RecursionError – maximum recursion depth exceeded

RecursionError in Python ist fast immer eine Endlosrekursion, kein zu kleines Limit. Warum ein höheres Limit den Interpreter abstürzen lässt.

Aufwand:
ca. 20 Min.
Voraussetzung:
Python 3, Editor, Terminal
Gilt für:
Python 3 (CPython)

Das Symptom

Ein Skript läuft kurz und bricht dann mit einem Traceback ab, in dem dieselbe Handvoll Zeilen immer wieder auftaucht:

  File "app.py", line 7, in flaeche
    return self.breite * self.hoehe
  [Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded

Manchmal steht am Ende noch ein Zusatz wie while calling a Python object oder in comparison. Der Kern bleibt derselbe: Python ist beim Aufrufen zu tief geraten und hat die Notbremse gezogen.

Die „Layer 8“-Wahrheit

Die Fehlermeldung nennt eine Zahl, und deshalb greifen die meisten reflexhaft zur Zahl: Limit hochsetzen, weiter. Das ist die falsche Baustelle. In der überwiegenden Mehrzahl der Fälle ist die Rekursion nicht zu tief, sondern unendlich – der Basisfall fehlt, oder er wird nie erreicht, weil das Argument bei jedem Aufruf gleich bleibt. Eine unendliche Rekursion wird auch mit dem zehnfachen Limit nicht endlich. Sie braucht nur zehnmal so lange, bis dieselbe Meldung erscheint.

Das Limit ist auch keine Schikane, sondern eine Schutzschaltung. Die Python-Dokumentation beschreibt es als die maximale Tiefe des Interpreter-Stacks und sagt ausdrücklich, wovor es schützt: davor, dass endlose Rekursion den C-Stack zum Überlaufen bringt und Python abstürzt. Jeder Python-Aufruf verbraucht eben auch echten Speicher im Unterbau des Interpreters, und der ist endlich. Wer das Limit weit hochdreht, entfernt die Sicherung vor der Leitung. Die Dokumentation formuliert das erstaunlich unverblümt: Das höchstmögliche Limit ist plattformabhängig, und ein zu hohes Limit kann zu einem Absturz führen. Aus einer Ausnahme mit Traceback wird dann ein Prozess, der wortlos verschwindet – das exakte Gegenteil einer Verbesserung.

Der Weg nach vorn ist deshalb unspektakulär: Traceback von unten lesen, den sich wiederholenden Block als Zyklus identifizieren, den Basisfall reparieren. Wo die Tiefe echt aus den Daten kommt, wird aus der Rekursion eine Schleife mit eigenem Stapel oder ein zwischengespeicherter Aufruf. Und wenn nach all dem noch immer feststeht, dass die Rekursion endlich, aber tief ist – dann, und wirklich erst dann, darf das Limit steigen. Mit Ansage, in Maßen und im Wissen, dass darunter kein Netz mehr gespannt ist.

Die echte, verifizierte Lösung

1000 % faktenbasiert. Jeder Befehl ist real, jeder Pfad existiert. Schritt für Schritt:

  1. 1.

    Den Traceback von unten lesen, nicht von oben

    Die letzten Zeilen vor der Ausnahme sind der ganze Fall: Sie wiederholen sich, und CPython fasst die Wiederholung sogar zusammen. Dieser sich wiederholende Block ist der Zyklus. Notiere dir die Funktionsnamen darin – mehr brauchst du für die Diagnose nicht.

    python3 skript.py 2>&1 | tail -n 20
    
  2. 2.

    Die Abbruchbedingung suchen – und feststellen, dass sie fehlt oder nie greift

    Jede Rekursion braucht einen Basisfall, der ohne weiteren Aufruf zurückkehrt, und einen Schritt, der das Problem bei jedem Aufruf echt verkleinert. Fehlt der Basisfall, oder wird das Argument nie kleiner (etwa weil n - 1 berechnet, aber n weitergereicht wird), läuft die Funktion bis ans Limit. Das ist der Normalfall hinter dieser Ausnahme.

    def fakultaet(n):
        if n <= 1:          # Basisfall: hier endet die Rekursion
            return 1
        return n * fakultaet(n - 1)   # Schritt: n wird echt kleiner
    
  3. 3.

    Das aktuelle Limit ansehen, statt es zu raten

    Bevor du an einer Schraube drehst, lies ab, wie sie steht. getrecursionlimit gibt den aktuellen Wert zurück – die maximale Tiefe des Interpreter-Stacks. Liegt deine erwartete Rekursionstiefe klar darunter, ist das Limit nicht dein Problem, sondern dein Code.

    python3 -c "import sys; print(sys.getrecursionlimit())"
    
  4. 4.

    Die Rekursion auflösen: Schleife statt Selbstaufruf

    Wo die Tiefe von den Daten abhängt und nicht von einem Denkfehler, ist die ehrlichste Lösung, gar nicht erst tief zu stapeln. Viele Rekursionen lassen sich mechanisch in eine Schleife übersetzen; ein Baum- oder Graphdurchlauf kommt mit einer eigenen Liste als Stapel aus. Der Speicher liegt dann auf dem Heap statt auf dem Stack, und das Limit ist kein Thema mehr.

    def alle_knoten(wurzel):
        stapel = [wurzel]
        gesehen = set()
        while stapel:
            knoten = stapel.pop()
            if id(knoten) in gesehen:   # schützt vor Zyklen
                continue
            gesehen.add(id(knoten))
            yield knoten
            stapel.extend(knoten.kinder)
    
  5. 5.

    Wiederholte Teilprobleme zwischenspeichern

    Bei Funktionen wie der naiven Fibonacci-Berechnung ist nicht die Tiefe das Problem, sondern die Zahl der Aufrufe. Ein Cache aus der Standardbibliothek macht aus exponentiell vielen Aufrufen lineare – ohne dass du die Funktion umschreiben musst.

    from functools import cache
    
    @cache
    def fib(n):
        return n if n < 2 else fib(n - 1) + fib(n - 2)
    
  6. 6.

    Das Limit nur anheben, wenn die Rekursion nachweislich endlich ist

    Erst wenn feststeht, dass die Rekursion terminiert und nur tief ist, ist setrecursionlimit ein legitimes Werkzeug. Die Dokumentation nennt genau diesen Fall: Ein Programm, das tiefe Rekursion braucht, auf einer Plattform, die ein höheres Limit trägt. Sie warnt im selben Atemzug, dass ein zu hohes Limit zum Absturz führen kann – also in kleinen Schritten und mit einem Wert, den du begründen kannst.

    import sys
    sys.setrecursionlimit(3000)   # nur bei belegbar endlicher, tiefer Rekursion
    

Häufige Fragen (FAQ)

?Kann ich das Limit einfach hochsetzen, dann läuft es doch?

Manchmal – und genau das macht es gefährlich. Die Python-Dokumentation schreibt zu sys.setrecursionlimit, das höchstmögliche Limit sei plattformabhängig und man solle es mit Bedacht ändern, weil ein zu hohes Limit zu einem Absturz führen kann. Der Grund steht direkt daneben: Das Limit soll verhindern, dass endlose Rekursion den C-Stack zum Überlaufen bringt und Python abstürzt. Wer das Limit hochdreht, tauscht also eine saubere Ausnahme mit Traceback gegen einen harten Absturz ohne Fehlermeldung ein. Bei einer echten Endlosrekursion gewinnt man damit nichts, sondern verliert nur die Diagnose. Legitim ist das Anheben nur, wenn die Rekursion nachweislich endlich, aber tief ist.

?Warum gibt es dieses Limit überhaupt?

Weil jeder Python-Funktionsaufruf im Unterbau auch Platz auf dem C-Stack des Interpreters belegt, und der ist endlich. Läuft er über, ist das kein abfangbarer Fehler mehr, sondern ein Absturz des gesamten Prozesses. Die Dokumentation beschreibt das Rekursionslimit deshalb ausdrücklich als die maximale Tiefe des Python-Interpreter-Stacks, die genau diesen Überlauf verhindert. Das Limit ist also kein Gängelband, sondern die Notbremse, die aus einem Absturz eine Ausnahme macht, die du sehen und behandeln kannst.

?Mein Code hat gar keine Rekursion – woher kommt der Fehler?

Dann ist sie versteckt. Typische Fälle: zwei Funktionen, die sich gegenseitig aufrufen; eine __getattr__-Methode, die auf ein Attribut zugreift, das es nicht gibt, und sich damit selbst erneut aufruft; ein __repr__, das das eigene Objekt formatiert; eine property, deren Getter auf denselben Namen statt auf das interne Feld zugreift; oder eine ringförmige Datenstruktur, durch die ein rekursiver Traversierer endlos im Kreis läuft. Der Traceback zeigt in all diesen Fällen dieselbe kurze Zeilenfolge immer wieder – das ist der Fingerabdruck.

Belege

Diese Seite ist gegen die folgenden Primärquellen geprüft – Hersteller, Standard oder Gesetzestext. Wer es nicht glaubt, muss es nicht: Da steht, wo es nachzulesen ist.

Zuletzt geprüft am . Dokumentation altert – ein Datum daneben ist der einzige ehrliche Umgang damit.

Auch zu finden unter

Verwandte Fehler

SWLästigCERTIFICATE_VERIFY_FAILED

pip: SSL: CERTIFICATE_VERIFY_FAILED

pip lädt keine Pakete wegen SSL-Zertifikatsfehler? Meist schneidet ein Firmen-Proxy mit oder die Zertifikate sind veraltet — beides ist lösbar.