Grundlegendes zum Python-Traceback

Grundlegendes zum Python-Traceback

Python druckt einen Traceback , wenn in Ihrem Code eine Ausnahme ausgelöst wird. Die Traceback-Ausgabe kann etwas überwältigend sein, wenn Sie sie zum ersten Mal sehen oder nicht wissen, was sie Ihnen sagt. Der Python-Traceback enthält jedoch eine Fülle von Informationen, mit denen Sie den Grund für die in Ihrem Code ausgelöste Ausnahme diagnostizieren und beheben können. Um ein besserer Python-Programmierer zu werden, ist es wichtig zu verstehen, welche Informationen ein Python-Traceback bereitstellt.

*Am Ende dieses Tutorials können Sie:*
  • Machen Sie Sinn für den nächsten Traceback, den Sie sehen

  • Erkennen Sie einige der häufigsten Rückverfolgungen

  • Protokollieren Sie einen Traceback erfolgreich, während die Ausnahme weiterhin behandelt wird

    *Kostenloser Bonus:* Link: [Klicken Sie hier, um unser kostenloses Python-Spickzettel zu erhalten], das Ihnen die Grundlagen von Python 3 zeigt, z. B. das Arbeiten mit Datentypen, Wörterbüchern, Listen und Python-Funktionen.

Was ist ein Python-Traceback?

Ein Traceback ist ein Bericht, der die Funktionsaufrufe enthält, die an einem bestimmten Punkt in Ihrem Code ausgeführt wurden. Tracebacks sind unter vielen Namen bekannt, einschließlich Stack Trace , Stack Traceback , Backtrace und möglicherweise anderen. In Python wird der Begriff traceback verwendet.

Wenn Ihr Programm zu einer Ausnahme führt, druckt Python den aktuellen Traceback, damit Sie wissen, was schief gelaufen ist. Das folgende Beispiel veranschaulicht diese Situation:

# example.py
def greet(someone):
    print('Hello, ' + someon)

greet('Chad')

Hier wird + greet () + mit dem Parameter + jemand + aufgerufen. In + greet () + wird dieser Variablenname jedoch nicht verwendet. Stattdessen wurde es im Aufruf + print () + als + someon + `falsch geschrieben.

*Hinweis:* In diesem Tutorial wird davon ausgegangen, dass Sie Python-Ausnahmen verstehen. Wenn Sie nicht vertraut sind oder nur eine Auffrischung wünschen, sollten Sie https://realpython.com/python-exceptions/[Python Exceptions: An Introduction] lesen.

Wenn Sie dieses Programm ausführen, erhalten Sie den folgenden Traceback:

$ python example.py
Traceback (most recent call last):
  File "/path/to/example.py", line 4, in <module>
    greet('Chad')
  File "/path/to/example.py", line 2, in greet
    print('Hello, ' + someon)
NameError: name 'someon' is not defined

Diese Traceback-Ausgabe enthält alle Informationen, die Sie zur Diagnose des Problems benötigen. In der letzten Zeile der Traceback-Ausgabe erfahren Sie, welche Art von Ausnahme ausgelöst wurde, sowie einige relevante Informationen zu dieser Ausnahme. Die vorherigen Zeilen des Tracebacks verweisen auf den Code, der zur Auslösung der Ausnahme geführt hat.

Im obigen Traceback war die Ausnahme ein "+ NameError ". Dies bedeutet, dass auf einen Namen (Variable, Funktion, Klasse) verwiesen wird, der nicht definiert wurde. In diesem Fall lautet der Name, auf den verwiesen wird, " jemand +".

Die letzte Zeile in diesem Fall enthält genügend Informationen, um das Problem zu beheben. Wenn Sie den Code nach dem Namen "+ someon +" durchsuchen, der falsch geschrieben ist, weisen Sie in die richtige Richtung. Oft ist Ihr Code jedoch viel komplizierter.

Wie liest man einen Python-Traceback?

Das Python-Traceback enthält viele hilfreiche Informationen, wenn Sie versuchen, den Grund für die Auslösung einer Ausnahme in Ihrem Code zu ermitteln. In diesem Abschnitt werden Sie verschiedene Tracebacks durchgehen, um die verschiedenen Informationen zu verstehen, die in einem Traceback enthalten sind.

Python Traceback Übersicht

Zu jedem Python-Traceback gibt es mehrere Abschnitte, die wichtig sind. Das folgende Diagramm zeigt die verschiedenen Teile:

Ein Beispiel für einen Python-Traceback mit Call-Outs.

In Python lesen Sie den Traceback am besten von unten nach oben:

  1. Blaues Kästchen: Die letzte Zeile des Tracebacks ist die Fehlermeldung. Es enthält den Auslösernamen, der ausgelöst wurde.

  2. Grünes Kästchen: Nach dem Ausnahmenamen steht die Fehlermeldung. Diese Nachricht enthält normalerweise hilfreiche Informationen zum Verständnis des Grundes für die Auslösung der Ausnahme.

  3. Gelbes Kästchen: Weiter oben im Traceback befinden sich die verschiedenen Funktionsaufrufe, die sich von unten nach oben bewegen, zuletzt bis zuletzt. Diese Anrufe werden durch zweizeilige Einträge für jeden Anruf dargestellt. Die erste Zeile jedes Aufrufs enthält Informationen wie den Dateinamen, die Zeilennummer und den Modulnamen, die alle angeben, wo sich der Code befindet.

  4. Rote Unterstreichung: Die zweite Zeile für diese Aufrufe enthält den tatsächlich ausgeführten Code.

Es gibt einige Unterschiede zwischen der Traceback-Ausgabe, wenn Sie Ihren Code in der Befehlszeile ausführen, und der Ausführung von Code in der REPL. Unten finden Sie denselben Code aus dem vorherigen Abschnitt, der in einer REPL ausgeführt wurde, und die daraus resultierende Traceback-Ausgabe:

>>>

>>> def greet(someone):
...   print('Hello, ' + someon)
...
>>> greet('Chad')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in greet
NameError: name 'someon' is not defined

Beachten Sie, dass Sie anstelle von Dateinamen "" <stdin> "" erhalten. Dies ist sinnvoll, da Sie den Code über die Standardeingabe eingegeben haben. Außerdem werden die ausgeführten Codezeilen im Traceback nicht angezeigt.

*Hinweis* : Wenn Sie es gewohnt sind, Stack-Traces in anderen Programmiersprachen zu sehen, werden Sie einen großen Unterschied in der Art und Weise feststellen, wie ein Python-Traceback im Vergleich aussieht. Die meisten anderen Sprachen drucken die Ausnahme oben und gehen dann von oben nach unten, die letzten Anrufe zu den letzten.

Es wurde bereits gesagt, aber nur um es noch einmal zu wiederholen, sollte ein Python-Traceback von unten nach oben gelesen werden. Dies ist sehr hilfreich, da der Traceback ausgedruckt wird und Ihr Terminal (oder wo immer Sie den Traceback lesen) normalerweise am unteren Rand der Ausgabe landet, sodass Sie den perfekten Ort zum Lesen des Tracebacks finden.

Spezifische exemplarische Vorgehensweise für Rückverfolgungen

Wenn Sie eine bestimmte Traceback-Ausgabe durchgehen, können Sie besser verstehen und sehen, welche Informationen der Traceback Ihnen liefert.

Der folgende Code wird in den folgenden Beispielen verwendet, um die Informationen zu veranschaulichen, die Ihnen ein Python-Traceback gibt:

# greetings.py
def who_to_greet(person):
    return person if person else input('Greet who? ')

def greet(someone, greeting='Hello'):
    print(greeting + ', ' + who_to_greet(someone))

def greet_many(people):
    for person in people:
        try:
            greet(person)
        except Exception:
            print('hi, ' + person)

Hier nimmt + who_to_greet () + einen Wert, + person +, und gibt ihn entweder zurück oder fordert stattdessen zur Rückgabe eines Werts auf.

Dann nimmt + greet () + einen Namen, der begrüßt werden soll, + jemand + und einen optionalen + Gruß + Wert und ruft + print () + auf. + who_to_greet () + wird auch mit dem übergebenen Wert + jemand + aufgerufen.

Schließlich wird "+ greet_many () " die Liste der " people " durchlaufen und " greet () " aufrufen. Wenn beim Aufrufen von " greet () +" eine Ausnahme ausgelöst wird, wird eine einfache Sicherungsbegrüßung gedruckt.

Dieser Code enthält keine Fehler, die dazu führen würden, dass eine Ausnahme ausgelöst wird, solange die richtige Eingabe bereitgestellt wird.

Wenn Sie einen Aufruf von "+ greet () " am Ende von " greetings.py " hinzufügen und ein Schlüsselwortargument angeben, das nicht erwartet wird (z. B. " greet" ("Chad", greting = "Yo")). ) + `), dann erhalten Sie folgenden Traceback:

$ python example.py
Traceback (most recent call last):
  File "/path/to/greetings.py", line 19, in <module>
    greet('Chad', greting='Yo')
TypeError: greet() got an unexpected keyword argument 'greting'

Noch einmal, mit einem Python-Traceback ist es am besten, rückwärts zu arbeiten und die Ausgabe nach oben zu verschieben. Ab der letzten Zeile des Tracebacks können Sie sehen, dass die Ausnahme ein "+ TypeError " war. Die Nachrichten, die dem Ausnahmetyp folgen, alles nach dem Doppelpunkt, geben Ihnen einige großartige Informationen. Es zeigt Ihnen, dass " greet () " mit einem Keyword-Argument aufgerufen wurde, das nicht erwartet wurde. Der unbekannte Argumentname wird Ihnen auch gegeben: ` greting +`.

Wenn Sie nach oben gehen, sehen Sie die Zeile, die zur Ausnahme geführt hat. In diesem Fall ist es der Aufruf "+ greet () ", den wir am Ende von " greetings.py +" hinzugefügt haben.

In der nächsten Zeile erhalten Sie den Pfad zu der Datei, in der der Code vorhanden ist, die Zeilennummer der Datei, in der sich der Code befindet, und in welchem ​​Modul er sich befindet. In diesem Fall sehen wir hier nur "+ <Modul> +", da unser Code keine anderen Python-Module verwendet. Dies bedeutet, dass dies die Datei ist, die ausgeführt wird.

Mit einer anderen Datei und einer anderen Eingabe können Sie sehen, dass der Traceback Sie wirklich in die richtige Richtung weist, um das Problem zu finden. Wenn Sie mitmachen, entfernen Sie den fehlerhaften Aufruf "+ greet () " am Ende von " greetings.py +" und fügen Sie die folgende Datei zu Ihrem Verzeichnis hinzu:

# example.py
from greetings import greet

greet(1)

Hier haben Sie eine weitere Python-Datei eingerichtet, die Ihr vorheriges Modul "+ greetings.py " importiert und " greet () " verwendet. Folgendes passiert, wenn Sie jetzt " example.py +" ausführen:

$ python example.py
Traceback (most recent call last):
  File "/path/to/example.py", line 3, in <module>
    greet(1)
  File "/path/to/greetings.py", line 5, in greet
    print(greeting + ', ' + who_to_greet(someone))
TypeError: must be str, not int

Die in diesem Fall ausgelöste Ausnahme ist wieder ein "+ TypeError +", aber diesmal ist die Nachricht etwas weniger hilfreich. Es sagt Ihnen, dass irgendwo im Code erwartet wurde, dass es mit einer Zeichenfolge funktioniert, aber eine Ganzzahl angegeben wurde.

Wenn Sie nach oben gehen, sehen Sie die Codezeile, die ausgeführt wurde. Dann die Datei- und Zeilennummer des Codes. Dieses Mal erhalten wir jedoch anstelle von "+ <Modul> " den Namen der Funktion, die ausgeführt wurde: " greet () +".

Wenn wir zur nächsten ausgeführten Codezeile übergehen, sehen wir, dass unser problematischer Aufruf + greet () + in einer Ganzzahl übergeben wird.

Manchmal, nachdem eine Ausnahme ausgelöst wurde, fängt ein anderes Codebit diese Ausnahme ab und führt auch zu einer Ausnahme. In diesen Situationen gibt Python alle Ausnahme-Tracebacks in der Reihenfolge aus, in der sie empfangen wurden, und endet erneut mit dem Traceback der zuletzt ausgelösten Ausnahme.

Da dies etwas verwirrend sein kann, finden Sie hier ein Beispiel. Fügen Sie einen Aufruf von + greet_many () + am Ende von + greetings.py + hinzu:

# greetings.py
...
greet_many(['Chad', 'Dan', 1])

Dies sollte dazu führen, dass Grüße an alle drei Personen gedruckt werden. Wenn Sie diesen Code jedoch ausführen, sehen Sie ein Beispiel für die Ausgabe mehrerer Tracebacks:

$ python greetings.py
Hello, Chad
Hello, Dan
Traceback (most recent call last):
  File "greetings.py", line 10, in greet_many
    greet(person)
  File "greetings.py", line 5, in greet
    print(greeting + ', ' + who_to_greet(someone))
TypeError: must be str, not int

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "greetings.py", line 14, in <module>
    greet_many(['Chad', 'Dan', 1])
  File "greetings.py", line 12, in greet_many
    print('hi, ' + person)
TypeError: must be str, not int

Beachten Sie die hervorgehobene Zeile, die in der obigen Ausgabe mit "+ Während der Behandlung +" beginnt. Zwischen allen Rückverfolgungen wird diese Zeile angezeigt. Die Meldung ist sehr klar, während Ihr Code versuchte, die vorherige Ausnahme zu behandeln, wurde eine weitere Ausnahme ausgelöst.

*Hinweis* : Die Python-Funktion zum Anzeigen der vorherigen Rückverfolgungs-Tracebacks wurde in Python 3 hinzugefügt. In Python 2 erhalten Sie nur den Traceback der letzten Ausnahme.

Sie haben die vorherige Ausnahme bereits gesehen, als Sie + greet () + mit einer Ganzzahl aufgerufen haben. Da wir der Liste der zu begrüßenden Personen ein "+ 1 " hinzugefügt haben, können wir dasselbe Ergebnis erwarten. Die Funktion ` greet_many () ` umschließt jedoch den Aufruf von ` greet () ` in einem ` try ` und` + außer + `Block. Nur für den Fall, dass " greet () " zu einer Ausnahme führt, möchte " greet_many () +" eine Standardbegrüßung drucken.

Der relevante Teil von + greetings.py + wird hier wiederholt:

def greet_many(people):
    for person in people:
        try:
            greet(person)
        except Exception:
            print('hi, ' + person)

Wenn also "+ greet () " aufgrund der fehlerhaften Ganzzahl-Eingabe zu " TypeError " führt, behandelt " greet_many () +" diese Ausnahme und versucht, eine einfache Begrüßung zu drucken. Hier führt der Code zu einer weiteren, ähnlichen Ausnahme. Es wird immer noch versucht, eine Zeichenfolge und eine Ganzzahl hinzuzufügen.

Wenn Sie die gesamte Traceback-Ausgabe anzeigen, können Sie erkennen, was die eigentliche Ursache für eine Ausnahme sein könnte. Wenn Sie die letzte Ausnahme und den daraus resultierenden Traceback sehen, können Sie manchmal immer noch nicht erkennen, was falsch ist. In diesen Fällen erhalten Sie eine bessere Vorstellung von der Grundursache, wenn Sie zu den vorherigen Ausnahmen wechseln.

Was sind einige häufige Rückverfolgungen in Python?

Wenn Sie wissen, wie ein Python-Traceback gelesen wird, wenn Ihr Programm eine Ausnahme auslöst, kann dies beim Programmieren sehr hilfreich sein. Wenn Sie jedoch einige der gängigsten Tracebacks kennen, kann dies auch Ihren Prozess beschleunigen.

Hier sind einige häufige Ausnahmen, auf die Sie stoßen könnten, die Gründe, warum sie angesprochen werden und was sie bedeuten, und die Informationen, die Sie in ihren Rückverfolgungen finden können.

+ AttributeError +

Der + AttributeError + wird ausgelöst, wenn Sie versuchen, auf ein Attribut für ein Objekt zuzugreifen, für das dieses Attribut nicht definiert ist. In der Python-Dokumentation wird definiert, wann diese Ausnahme ausgelöst wird:

_ Wird ausgelöst, wenn eine Attributreferenz oder Zuweisung fehlschlägt. (Source) _

Hier ist ein Beispiel für das Auslösen von "+ AttributeError +":

>>>

>>> an_int = 1
>>> an_int.an_attribute
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute 'an_attribute'

Die Fehlermeldung für einen "+ AttributeError " zeigt an, dass auf den spezifischen Objekttyp " int " in diesem Fall nicht auf das Attribut " an_attribute +" zugegriffen werden kann. Wenn Sie den + AttributeError + in der Fehlermeldung sehen, können Sie schnell erkennen, auf welches Attribut Sie zugreifen wollten und wohin Sie gehen müssen, um es zu beheben.

Wenn Sie diese Ausnahme erhalten, bedeutet dies meistens, dass Sie wahrscheinlich mit einem Objekt arbeiten, das nicht dem erwarteten Typ entspricht:

>>>

>>> a_list = (1, 2)
>>> a_list.append(3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'append'

Im obigen Beispiel erwarten Sie möglicherweise, dass + a_list + vom Typ + list + ist, das eine Methode namens `+ .append () + hat `. Wenn Sie die Ausnahme "+ AttributeError " erhalten und feststellen, dass sie ausgelöst wurde, als Sie versuchen, " .append () +" aufzurufen, werden Sie darauf hingewiesen, dass Sie sich wahrscheinlich nicht mit dem erwarteten Objekttyp befassen.

Dies ist häufig der Fall, wenn Sie erwarten, dass ein Objekt von einem Funktions- oder Methodenaufruf eines bestimmten Typs zurückgegeben wird, und Sie ein Objekt vom Typ "+ None " erhalten. In diesem Fall lautet die Fehlermeldungszeile " AttributeError: Das Objekt" NoneType "hat kein Attribut" append "+".

+ ImportError +

Der + ImportError + wird ausgelöst, wenn bei einer Importanweisung ein Fehler auftritt. Sie erhalten diese Ausnahme oder die Unterklasse "+ ModuleNotFoundError +", wenn das zu importierende Modul nicht gefunden werden kann oder wenn Sie versuchen, etwas aus einem Modul zu importieren, das im Modul nicht vorhanden ist. In der Python-Dokumentation wird definiert, wann diese Ausnahme ausgelöst wird:

_ Wird ausgelöst, wenn die import-Anweisung Probleme beim Laden eines Moduls hat. Wird auch ausgelöst, wenn die "Von-Liste" in "+ Von …​" import + `hat einen Namen, der nicht gefunden werden kann. (Source) _

Hier ist ein Beispiel für das Auslösen von "+ ImportError " und " ModuleNotFoundError +":

>>>

>>> import asdf
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'asdf'
>>> from collections import asdf
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name 'asdf'

Im obigen Beispiel sehen Sie, dass der Versuch, ein nicht vorhandenes Modul zu importieren, "+ asdf ", zu " ModuleNotFoundError " führt. Wenn Sie versuchen, etwas, das nicht existiert, " asdf ", aus einem Modul zu importieren, das existiert, " Sammlungen ", führt dies zu einem " ImportError ". Die Fehlermeldungen am unteren Rand der Tracebacks zeigen an, welches Objekt nicht importiert werden konnte, in beiden Fällen " asdf +".

+ IndexError +

Der + IndexError + wird ausgelöst, wenn Sie versuchen, einen Index aus einer Sequenz abzurufen, z. B. + list + oder ein + tuple + und den Index wird nicht in der Sequenz gefunden. In der Python-Dokumentation wird definiert, wann diese Ausnahme ausgelöst wird:

_ Wird ausgelöst, wenn ein Sequenzindex außerhalb des Bereichs liegt. (Source) _

Hier ist ein Beispiel, das den "+ IndexError +" auslöst:

>>>

>>> a_list = ['a', 'b']
>>> a_list[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

Die Fehlermeldung für einen + IndexError + enthält keine guten Informationen. Sie können sehen, dass Sie eine Sequenzreferenz haben, die "+ außerhalb des Bereichs " liegt, und den Typ der Sequenz haben, in diesem Fall eine " Liste +". Diese Informationen in Kombination mit dem Rest des Tracebacks reichen normalerweise aus, um schnell zu ermitteln, wie das Problem behoben werden kann.

+ KeyError +

Ähnlich wie beim "+ IndexError " wird der " KeyError " ausgelöst, wenn Sie versuchen, auf einen Schlüssel zuzugreifen, der nicht in der Zuordnung enthalten ist, normalerweise ein " dict ". Stellen Sie sich dies als " IndexError +" vor, jedoch für dictionaries. In der Python-Dokumentation wird definiert, wann diese Ausnahme ausgelöst wird:

_ Wird ausgelöst, wenn kein Mapping-Schlüssel (Wörterbuchschlüssel) im Satz vorhandener Schlüssel gefunden wird. (Source) _

Hier ist ein Beispiel für das Auslösen von "+ KeyError +":

>>>

>>> a_dict['b']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'b'

Die Fehlermeldung für einen + KeyError + gibt Ihnen den Schlüssel, der nicht gefunden werden konnte. Dies ist nicht viel zu tun, reicht jedoch in Kombination mit dem Rest des Tracebacks normalerweise aus, um das Problem zu beheben.

Weitere Informationen zu + KeyError + finden Sie unter https://realpython.com/python-keyerror/[Python KeyError-Ausnahmen und deren Behandlung.

+ NameError +

Der "+ NameError +" wird ausgelöst, wenn Sie auf eine Variable, ein Modul, eine Klasse, eine Funktion oder einen anderen Namen verwiesen haben, der in Ihrem Code nicht definiert wurde. In der Python-Dokumentation wird definiert, wann diese Ausnahme ausgelöst wird:

_ Wird ausgelöst, wenn kein lokaler oder globaler Name gefunden wird. (Source) _

Im folgenden Code nimmt + greet () + einen Parameter + person + an. In der Funktion selbst wurde dieser Parameter jedoch mit "+ persn +" falsch geschrieben:

>>>

>>> def greet(person):
...     print(f'Hello, {persn}')
>>> greet('World')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in greet
NameError: name 'persn' is not defined

Die Fehlermeldung des Tracebacks + NameError + gibt Ihnen den Namen an, der fehlt. Im obigen Beispiel handelt es sich um eine falsch geschriebene Variable oder einen falsch geschriebenen Parameter für die übergebene Funktion.

Ein "+ NameError +" wird auch ausgelöst, wenn es sich um den Parameter handelt, den Sie falsch geschrieben haben:

>>>

>>> def greet(persn):
...     print(f'Hello, {person}')
>>> greet('World')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in greet
NameError: name 'person' is not defined

Hier scheint es, als hätten Sie nichts falsch gemacht. Die letzte Zeile, die im Traceback ausgeführt und referenziert wurde, sieht gut aus. Wenn Sie sich in dieser Situation befinden, müssen Sie in Ihrem Code nachsehen, wo die Variable + person + verwendet und definiert wird. Hier sehen Sie schnell, dass der Parametername falsch geschrieben wurde.

+ SyntaxError +

Der + SyntaxError + wird ausgelöst, wenn Ihr Code eine falsche Python-Syntax enthält. In der Python-Dokumentation wird definiert, wann diese Ausnahme ausgelöst wird:

_ Wird ausgelöst, wenn der Parser auf einen Syntaxfehler stößt. (Source) _

Unten ist das Problem ein fehlender Doppelpunkt, der sich am Ende der Funktionsdefinitionszeile befinden sollte. In der Python-REPL wird dieser Syntaxfehler sofort nach dem Drücken der Eingabetaste ausgelöst:

>>>

>>> def greet(person)
  File "<stdin>", line 1
    def greet(person)
                    ^
SyntaxError: invalid syntax

Die Fehlermeldung des "+ SyntaxError " zeigt nur an, dass ein Problem mit der Syntax Ihres Codes aufgetreten ist. Wenn Sie in die obigen Zeilen schauen, erhalten Sie die Zeile mit dem Problem und normalerweise ein ` ^ +` (Caret), das auf die Problemstelle zeigt. Hier fehlt der Doppelpunkt in der Anweisung + def + der Funktion.

Bei + SyntaxError + Tracebacks fehlt außerdem die reguläre erste Zeile + Traceback (letzter Aufruf zuletzt): +. Dies liegt daran, dass der "+ SyntaxError +" ausgelöst wird, wenn Python versucht, Ihren Code zu analysieren, und die Zeilen nicht tatsächlich ausgeführt werden.

+ TypeError +

Der + TypeError + wird ausgelöst, wenn Ihr Code versucht, etwas mit einem Objekt zu tun, das dies nicht kann, z. B. wenn Sie versuchen, einer Ganzzahl eine Zeichenfolge hinzuzufügen, oder wenn Sie + len () + für ein Objekt aufrufen, dessen Länge ist nicht definiert. In der Python-Dokumentation wird definiert, wann diese Ausnahme ausgelöst wird:

_ Wird ausgelöst, wenn eine Operation oder Funktion auf ein Objekt eines unangemessenen Typs angewendet wird. (Source) _

Es folgen einige Beispiele für das Auslösen von "+ TypeError +":

>>>

>>> 1 + '1'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> '1' + 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be str, not int
>>> len(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'int' has no len()

Alle obigen Beispiele zum Auslösen eines + TypeError + führen zu einer Fehlermeldung mit unterschiedlichen Meldungen. Jeder von ihnen macht einen ziemlich guten Job, um Sie darüber zu informieren, was falsch ist.

Die ersten beiden Beispiele versuchen, Zeichenfolgen und Ganzzahlen zusammenzufügen. Sie unterscheiden sich jedoch geringfügig:

  • Der erste ist der Versuch, einem + int + ein + str + hinzuzufügen. *Der zweite versucht, einem + str + ein + int + hinzuzufügen.

Die Fehlermeldungen spiegeln diese Unterschiede wider.

Das letzte Beispiel versucht, "+ len () " auf einem " int " aufzurufen. Die Fehlermeldung zeigt an, dass Sie dies mit einem " int +" nicht tun können.

+ ValueError +

Der "+ ValueError " wird ausgelöst, wenn der Wert des Objekts nicht korrekt ist. Sie können sich dies als einen " IndexError " vorstellen, der ausgelöst wird, weil der Wert des Index nicht im Bereich der Sequenz liegt. Nur der " ValueError +" ist für einen allgemeineren Fall. In der Python-Dokumentation wird definiert, wann diese Ausnahme ausgelöst wird:

_ Wird ausgelöst, wenn eine Operation oder Funktion ein Argument mit dem richtigen Typ, aber einem unangemessenen Wert erhält und die Situation nicht durch eine genauere Ausnahme wie "+ IndexError +" beschrieben wird. (Source) _

Hier sind zwei Beispiele für das Auslösen von "+ ValueError +":

>>>

>>> a, b, c = [1, 2]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: not enough values to unpack (expected 3, got 2)
>>> a, b = [1, 2, 3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: too many values to unpack (expected 2)

Die Fehlermeldung "+ ValueError +" in diesen Beispielen zeigt Ihnen genau, wo das Problem mit den Werten liegt:

  1. Im ersten Beispiel versuchen Sie, zu viele Werte zu entpacken. Die Fehlermeldung zeigt sogar an, dass Sie erwartet haben, 3 Werte zu entpacken, aber 2 Werte erhalten haben.

  2. Im zweiten Beispiel besteht das Problem darin, dass Sie zu viele Werte und nicht genügend Variablen zum Entpacken erhalten.

Wie protokolliere ich einen Traceback?

Wenn Sie eine Ausnahme und das daraus resultierende Python-Traceback erhalten, müssen Sie entscheiden, was Sie dagegen tun möchten. Normalerweise ist das Korrigieren Ihres Codes der erste Schritt, aber manchmal liegt das Problem in unerwarteten oder falschen Eingaben. Es ist zwar gut, diese Situationen in Ihrem Code zu berücksichtigen, aber manchmal ist es auch sinnvoll, die Ausnahme auszuschalten oder auszublenden, indem Sie den Traceback protokollieren und etwas anderes tun.

Hier ist ein realistischeres Beispiel für Code, der einige Python-Tracebacks zum Schweigen bringen muss. In diesem Beispiel wird die + Anfragen + Bibliothek verwendet. Weitere Informationen finden Sie unter Python’s Requests Library (Guide):

# urlcaller.py
import sys
import requests

response = requests.get(sys.argv[1])

print(response.status_code, response.content)

Dieser Code funktioniert gut. Wenn Sie dieses Skript ausführen und ihm eine URL als Befehlszeilenargument geben, ruft es die URL auf und druckt dann den HTTP-Statuscode und den Inhalt aus der Antwort. Es funktioniert sogar, wenn die Antwort ein HTTP-Fehlerstatus war:

$ python urlcaller.py https://httpbin.org/status/200
200 b''
$ python urlcaller.py https://httpbin.org/status/500
500 b''

Manchmal ist die URL, die Ihr Skript zum Abrufen erhält, jedoch nicht vorhanden oder der Hostserver ist ausgefallen. In diesen Fällen löst dieses Skript jetzt eine nicht erfasste Ausnahme "+ ConnectionError +" aus und gibt einen Traceback aus:

$ python urlcaller.py http://thisurlprobablydoesntexist.com
...
During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "urlcaller.py", line 5, in <module>
    response = requests.get(sys.argv[1])
  File "/path/to/requests/api.py", line 75, in get
    return request('get', url, params=params,* *kwargs)
  File "/path/to/requests/api.py", line 60, in request
    return session.request(method=method, url=url, **kwargs)
  File "/path/to/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/path/to/requests/sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "/path/to/requests/adapters.py", line 516, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='thisurlprobablydoesntexist.com', port=80): Max retries exceeded with url:/(Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7faf9d671860>: Failed to establish a new connection: [Errno -2] Name or service not known',))

Der Python-Traceback hier kann sehr lang sein, wobei viele andere Ausnahmen ausgelöst werden und schließlich dazu führen, dass der "+ ConnectionError " von " Anfragen " selbst ausgelöst wird. Wenn Sie den Traceback für die letzten Ausnahmen nach oben verschieben, können Sie sehen, dass das Problem in unserem Code mit Zeile 5 von " urlcaller.py +" begonnen hat.

Wenn Sie die fehlerhafte Zeile in einen https://realpython.com/python-exceptions/#the-try-and-except-block-handling-exceptions [+ try + und + außer + block] einschließen, fangen Sie den entsprechenden ab Mit Ausnahme kann Ihr Skript weiterhin mit mehr Eingaben arbeiten:

# urlcaller.py
...
try:
    response = requests.get(sys.argv[1])
except requests.exceptions.ConnectionError:
    print(-1, 'Connection Error')
else:
    print(response.status_code, response.content)

Der obige Code verwendet eine + else + -Klausel mit den Blöcken + try + und + außer +. Wenn Sie mit dieser Funktion von Python nicht vertraut sind, lesen Sie den Abschnitt über die Klausel + else + unter Python Exceptions: An Introduction.

Wenn Sie nun das Skript mit einer URL ausführen, die dazu führt, dass ein "+ ConnectionError " ausgelöst wird, wird ein " -1 " für den Statuscode und den Inhalt " Verbindungsfehler +" gedruckt:

$ python urlcaller.py http://thisurlprobablydoesntexist.com
-1 Connection Error

Das funktioniert super. In den meisten realen Systemen möchten Sie jedoch nicht nur die Ausnahme und den daraus resultierenden Traceback stummschalten, sondern den Traceback protokollieren. Durch das Protokollieren von Tracebacks können Sie besser verstehen, was in Ihren Programmen schief geht.

*Hinweis:* Weitere Informationen zum Python-Protokollierungssystem finden Sie unter https://realpython.com/python-logging/[Logging in Python].

Sie können den Traceback im Skript protokollieren, indem Sie das Paket "+ logging " importieren, einen Logger abrufen und " .exception () " für diesen Logger im Abschnitt " " des " try " und "" aufrufen außer + `Block. Ihr endgültiges Skript sollte ungefähr wie folgt aussehen:

# urlcaller.py
import logging
import sys
import requests

logger = logging.getLogger(__name__)

try:
    response = requests.get(sys.argv[1])
except requests.exceptions.ConnectionError as e:
    logger.exception()
    print(-1, 'Connection Error')
else:
    print(response.status_code, response.content)

Wenn Sie nun das Skript für eine problematische URL ausführen, werden die erwarteten "+ -1 " und " Verbindungsfehler +" gedruckt, aber auch der Traceback protokolliert:

$ python urlcaller.py http://thisurlprobablydoesntexist.com
...
  File "/path/to/requests/adapters.py", line 516, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='thisurlprobablydoesntexist.com', port=80): Max retries exceeded with url:/(Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7faf9d671860>: Failed to establish a new connection: [Errno -2] Name or service not known',))
-1 Connection Error

Standardmäßig sendet Python Protokollnachrichten an den Standardfehler (+ stderr +). Es sieht so aus, als hätten wir die Traceback-Ausgabe überhaupt nicht unterdrückt. Wenn Sie es jedoch erneut aufrufen, während Sie das + stderr + umleiten, können Sie sehen, dass das Protokollierungssystem funktioniert, und wir können unsere Protokolle für später speichern:

$ python urlcaller.py http://thisurlprobablydoesntexist.com 2> my-logs.log
-1 Connection Error

Fazit

Der Python-Traceback enthält großartige Informationen, mit denen Sie herausfinden können, was in Ihrem Python-Code falsch läuft. Diese Rückverfolgungen können ein wenig einschüchternd aussehen, aber wenn Sie sie einmal aufgeschlüsselt haben, um zu sehen, was sie Ihnen zeigen wollen, können sie sehr hilfreich sein. Wenn Sie einige Rückverfolgungen Zeile für Zeile durchgehen, erhalten Sie ein besseres Verständnis der darin enthaltenen Informationen und können das Beste aus ihnen herausholen.

Wenn Sie beim Ausführen Ihres Codes eine Python-Traceback-Ausgabe erhalten, können Sie Ihren Code verbessern. Auf diese Weise versucht Python, Ihnen zu helfen.

Nachdem Sie nun wissen, wie man einen Python-Traceback liest, können Sie mehr über einige Tools und Techniken zur Diagnose der Probleme erfahren, über die Sie in Ihrer Traceback-Ausgabe informiert werden. Das in Python integrierte https://docs.python.org/3.7/library/traceback.html [+ traceback + module] kann zum Arbeiten mit und Überprüfen von Tracebacks verwendet werden. Das + traceback + Modul kann hilfreich sein, wenn Sie mehr aus der Traceback-Ausgabe herausholen möchten. Es wäre auch hilfreich, mehr über einige Techniken zum Debuggen Ihres Python-Codes zu erfahren.