632 Stimmen

Ausnahmebeschreibung und Stack-Trace, die eine Ausnahme verursacht haben, als String abrufen

Ich habe eine Menge Beiträge über Stack Trace und Ausnahmen in Python gesehen. Aber habe nicht gefunden, was ich brauche.

Ich habe ein Stück Python 2.7-Code, der eine Ausnahme auslösen kann. Ich möchte es abfangen und einem String seine vollständige Beschreibung und den Stack-Trace, der den Fehler verursacht hat (einfach alles, was wir auf der Konsole sehen). Ich brauche diese Zeichenfolge, um sie in ein Textfeld in der GUI zu drucken.

Etwa so:

try:
    method_that_can_raise_an_exception(params)
except Exception as e:
    print_to_textbox(complete_exception_description(e))

Das Problem ist: Was ist die Funktion complete_exception_description ?

1 Stimmen

Was ist falsch an: sys.exc_info() ?

0 Stimmen

Fyi, schließlich Blöcke werden immer entschuldigt, egal was afaik.

889voto

kindall Punkte 167554

Siehe die traceback Modul, insbesondere das format_exc() Funktion. Aquí .

import traceback

try:
    raise ValueError
except ValueError:
    tb = traceback.format_exc()
else:
    tb = "No error"
finally:
    print tb

18 Stimmen

Funktioniert dies nur bei dem letzten Fehler? Was passiert, wenn Sie beginnen, den Fehler an andere Codeteile weiterzugeben? Ich schreibe gerade eine log_error(err) función.

0 Stimmen

Es funktioniert mit dem Fehler, der abgefangen und behandelt wurde.

48 Stimmen

Zusätzlich zu dem, wonach ich gesucht habe, habe ich gerade erfahren, dass try kann eine else Klausel.

127voto

Lassen Sie uns einen anständig komplizierten Stacktrace erstellen, um zu demonstrieren, dass wir den vollständigen Stacktrace erhalten:

def raise_error():
    raise RuntimeError('something bad happened!')

def do_something_that_might_error():
    raise_error()

Protokollierung des vollständigen Stacktrace

Am besten ist es, einen Logger für Ihr Modul einzurichten. Er kennt den Namen des Moduls und ist in der Lage, die Ebenen zu ändern (neben anderen Attributen, wie z. B. Handler)

import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)

Und wir können diesen Logger verwenden, um den Fehler zu erhalten:

try:
    do_something_that_might_error()
except Exception as error:
    logger.exception(error)

Welche Protokolle:

ERROR:__main__:something bad happened!
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

Wir erhalten also die gleiche Ausgabe wie bei einem Fehler:

>>> do_something_that_might_error()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

Nur die Zeichenkette erhalten

Wenn Sie wirklich nur die Zeichenkette wollen, verwenden Sie die traceback.format_exc Funktion zu verwenden, um die Protokollierung der Zeichenkette zu demonstrieren:

import traceback
try:
    do_something_that_might_error()
except Exception as error:
    just_the_string = traceback.format_exc()
    logger.debug(just_the_string)

Welche Protokolle:

DEBUG:__main__:Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "<stdin>", line 2, in do_something_that_might_error
  File "<stdin>", line 2, in raise_error
RuntimeError: something bad happened!

1 Stimmen

Ist dies die beste Methode bei der Verwendung von Python 3 (im Vergleich zu z. B. einige der Antworten unten)?

1 Stimmen

@Yunti Ich glaube, diese API ist in Python 2 und 3 konsistent.

0 Stimmen

Die Formatierung dieser Antwort wurde auf Meta diskutiert: meta.stackoverflow.com/questions/386477/ .

93voto

don_vanchos Punkte 600

Pour Python 3.5+ :

Sie können also den Stacktrace Ihrer Ausnahme wie bei jeder anderen Ausnahme abrufen. verwenden traceback.TracebackException für sie (ersetzen Sie einfach ex mit Ihrer Ausnahme):

print("".join(traceback.TracebackException.from_exception(ex).format())

Ein erweitertes Beispiel und andere Funktionen, um dies zu tun:

import traceback

try:
    1/0
except Exception as ex:
    print("".join(traceback.TracebackException.from_exception(ex).format()) == traceback.format_exc() == "".join(traceback.format_exception(type(ex), ex, ex.__traceback__))) # This is True !!
    print("".join(traceback.TracebackException.from_exception(ex).format()))

Die Ausgabe sieht dann etwa so aus:

True
Traceback (most recent call last):
  File "untidsfsdfsdftled.py", line 29, in <module>
    1/0
ZeroDivisionError: division by zero

13 Stimmen

Brillant. Im Jahr 2022 ist dies effektiv die akzeptierte Antwort. Alle anderen Antworten sind entweder wesentlich weniger Pythonisch, verletzen die Kapselung der Privatsphäre oder arbeiten nur mit der aktuell ausgelösten Exception und können daher keine Tracebacks für beliebige Exception-Objekte erzeugen. @don_vanchos: Das mag alles sein, was Sie jemals auf StackOverflow gemacht haben und machen werden - aber es ist genug. Oh, ja. Es ist genug.

91voto

Erwin Mayer Punkte 16992

Mit Python 3 formatiert der folgende Code eine Exception Objekt genau so, wie man es mit traceback.format_exc() :

import traceback

try: 
    method_that_can_raise_an_exception(params)
except Exception as ex:
    print(''.join(traceback.format_exception(etype=type(ex), value=ex, tb=ex.__traceback__)))

Das hat den Vorteil, dass nur die Exception Objekt benötigt wird (dank der aufgezeichneten __traceback__ Attribut) und kann daher leichter als Argument an eine andere Funktion zur weiteren Verarbeitung übergeben werden.

3 Stimmen

Es ist besser als sys.exc_info(), die nicht gut OO-Stil und verwenden globale Variable ist.

1 Stimmen

Hier wird speziell gefragt, wie man den Traceback aus dem Exception-Objekt erhält, wie Sie es hier getan haben: stackoverflow.com/questions/11414894/

5 Stimmen

Es gibt einen einfacheren Python3-Weg ohne die Verwendung von .__traceback__ y type siehe stackoverflow.com/a/58764987/5717886

38voto

aeter Punkte 10812
>>> import sys
>>> import traceback
>>> try:
...   5 / 0
... except ZeroDivisionError as e:
...   type_, value_, traceback_ = sys.exc_info()
>>> traceback.format_tb(traceback_)
['  File "<stdin>", line 2, in <module>\n']
>>> value_
ZeroDivisionError('integer division or modulo by zero',)
>>> type_
<type 'exceptions.ZeroDivisionError'>
>>>
>>> 5 / 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ZeroDivisionError: integer division or modulo by zero

Sie verwenden sys.exc_info() um die Informationen und die Funktionen im traceback Modul, um es zu formatieren. Aquí sind einige Beispiele für die Formatierung.

Der gesamte Ausnahme-String ist bei:

>>> ex = traceback.format_exception(type_, value_, traceback_)
>>> ex
['Traceback (most recent call last):\n', '  File "<stdin>", line 2, in <module>\n', 'ZeroDivisionError: integer division or modulo by zero\n']

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X