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.

15voto

Mike N Punkte 5775

Für diejenigen, die Python-3

Verwendung von traceback Modul und exception.__traceback__ kann man den Stack-Trace wie folgt extrahieren:

  • sich die aktuell Stack-Trace mit traceback.extract_stack()
  • die letzten drei Elemente entfernen (da es sich um Einträge im Stapel handelt, die mich zu meiner Debug-Funktion geführt haben)
  • __traceback__ aus dem Ausnahmeobjekt mit traceback.extract_tb()
  • formatieren Sie das Ganze mit traceback.format_list()

    import traceback def exception_to_string(excp): stack = traceback.extract_stack()[:-3] + traceback.extract_tb(excp.traceback) # add limit=?? pretty = traceback.format_list(stack) return ''.join(pretty) + '\n {} {}'.format(excp.class,excp)

Eine einfache Demonstration:

def foo():
    try:
        something_invalid()
    except Exception as e:
        print(exception_to_string(e))

def bar():
    return foo()

Wir erhalten die folgende Ausgabe, wenn wir Folgendes aufrufen bar() :

  File "./test.py", line 57, in <module>
    bar()
  File "./test.py", line 55, in bar
    return foo()
  File "./test.py", line 50, in foo
    something_invalid()

  <class 'NameError'> name 'something_invalid' is not defined

4 Stimmen

Es sieht aus wie ein unlesbarer, komplizierter Code. Unter Python 3.5+ Es gibt einen eleganteren und einfacheren Weg: stackoverflow.com/a/58764987/5717886

10voto

samaspin Punkte 2191

Sie können auch das integrierte Python-Modul verwenden, cgitb um einige wirklich gute, schön formatierte Ausnahmeinformationen zu erhalten, einschließlich lokaler Variablenwerte, Quellcodekontext, Funktionsparameter usw..

Zum Beispiel für diesen Code...

import cgitb
cgitb.enable(format='text')

def func2(a, divisor):
    return a / divisor

def func1(a, b):
    c = b - 5
    return func2(a, c)

func1(1, 5)

erhalten wir diese Ausnahmeausgabe...

ZeroDivisionError
Python 3.4.2: C:\tools\python\python.exe
Tue Sep 22 15:29:33 2015

A problem occurred in a Python script.  Here is the sequence of
function calls leading up to the error, in the order they occurred.

 c:\TEMP\cgittest2.py in <module>()
    7 def func1(a, b):
    8   c = b - 5
    9   return func2(a, c)
   10
   11 func1(1, 5)
func1 = <function func1>

 c:\TEMP\cgittest2.py in func1(a=1, b=5)
    7 def func1(a, b):
    8   c = b - 5
    9   return func2(a, c)
   10
   11 func1(1, 5)
global func2 = <function func2>
a = 1
c = 0

 c:\TEMP\cgittest2.py in func2(a=1, divisor=0)
    3
    4 def func2(a, divisor):
    5   return a / divisor
    6
    7 def func1(a, b):
a = 1
divisor = 0
ZeroDivisionError: division by zero
    __cause__ = None
    __class__ = <class 'ZeroDivisionError'>
    __context__ = None
    __delattr__ = <method-wrapper '__delattr__' of ZeroDivisionError object>
    __dict__ = {}
    __dir__ = <built-in method __dir__ of ZeroDivisionError object>
    __doc__ = 'Second argument to a division or modulo operation was zero.'
    __eq__ = <method-wrapper '__eq__' of ZeroDivisionError object>
    __format__ = <built-in method __format__ of ZeroDivisionError object>
    __ge__ = <method-wrapper '__ge__' of ZeroDivisionError object>
    __getattribute__ = <method-wrapper '__getattribute__' of ZeroDivisionError object>
    __gt__ = <method-wrapper '__gt__' of ZeroDivisionError object>
    __hash__ = <method-wrapper '__hash__' of ZeroDivisionError object>
    __init__ = <method-wrapper '__init__' of ZeroDivisionError object>
    __le__ = <method-wrapper '__le__' of ZeroDivisionError object>
    __lt__ = <method-wrapper '__lt__' of ZeroDivisionError object>
    __ne__ = <method-wrapper '__ne__' of ZeroDivisionError object>
    __new__ = <built-in method __new__ of type object>
    __reduce__ = <built-in method __reduce__ of ZeroDivisionError object>
    __reduce_ex__ = <built-in method __reduce_ex__ of ZeroDivisionError object>
    __repr__ = <method-wrapper '__repr__' of ZeroDivisionError object>
    __setattr__ = <method-wrapper '__setattr__' of ZeroDivisionError object>
    __setstate__ = <built-in method __setstate__ of ZeroDivisionError object>
    __sizeof__ = <built-in method __sizeof__ of ZeroDivisionError object>
    __str__ = <method-wrapper '__str__' of ZeroDivisionError object>
    __subclasshook__ = <built-in method __subclasshook__ of type object>
    __suppress_context__ = False
    __traceback__ = <traceback object>
    args = ('division by zero',)
    with_traceback = <built-in method with_traceback of ZeroDivisionError object>

The above is a description of an error in a Python program.  Here is
the original traceback:

Traceback (most recent call last):
  File "cgittest2.py", line 11, in <module>
    func1(1, 5)
  File "cgittest2.py", line 9, in func1
    return func2(a, c)
  File "cgittest2.py", line 5, in func2
    return a / divisor
ZeroDivisionError: division by zero

2 Stimmen

Hut ab, dass Sie ein Modul entwickelt haben, von dem ich nicht einmal wusste, dass es in der Standardbibliothek existiert.

10voto

Rune Kaagaard Punkte 6296

Wenn Ihr Ziel ist, die Ausnahme und die Stacktrace-Meldung genau so aussehen zu lassen, wie wenn Python einen Fehler auslöst, funktioniert das Folgende sowohl in Python 2+3:

import sys, traceback

def format_stacktrace():
    parts = ["Traceback (most recent call last):\n"]
    parts.extend(traceback.format_stack(limit=25)[:-2])
    parts.extend(traceback.format_exception(*sys.exc_info())[1:])
    return "".join(parts)

# EXAMPLE BELOW...

def a():
    b()

def b():
    c()

def c():
    d()

def d():
    assert False, "Noooh don't do it."

print("THIS IS THE FORMATTED STRING")
print("============================\n")

try:
    a()
except:
    stacktrace = format_stacktrace()
    print(stacktrace)

print("THIS IS HOW PYTHON DOES IT")
print("==========================\n")
a()

Es funktioniert durch das Entfernen der letzten format_stacktrace() Aufruf vom Stapel zu nehmen und den Rest zu verbinden. Wenn das obige Beispiel ausgeführt wird, ergibt sich die folgende Ausgabe:

THIS IS THE FORMATTED STRING
============================

Traceback (most recent call last):
  File "test.py", line 31, in <module>
    a()
  File "test.py", line 12, in a
    b()
  File "test.py", line 16, in b
    c()
  File "test.py", line 20, in c
    d()
  File "test.py", line 24, in d
    assert False, "Noooh don't do it."
AssertionError: Noooh don't do it.

THIS IS HOW PYTHON DOES IT
==========================

Traceback (most recent call last):
  File "test.py", line 38, in <module>
    a()
  File "test.py", line 12, in a
    b()
  File "test.py", line 16, in b
    c()
  File "test.py", line 20, in c
    d()
  File "test.py", line 24, in d
    assert False, "Noooh don't do it."
AssertionError: Noooh don't do it.

9voto

SamuelN Punkte 136

Wenn Sie die gleichen Informationen erhalten möchten, die gegeben werden, wenn eine Ausnahme nicht behandelt wird, können Sie wie folgt vorgehen. Machen Sie import traceback und dann:

try:
    ...
except Exception as e:
    print(traceback.print_tb(e.__traceback__))

Ich verwende Python 3.7.

3 Stimmen

Gute Antwort! Kleine Anmerkung: traceback.print_tb() druckt bereits. Das externe print() gibt also None zurück und die Ausgabe ist der Stacktrace, gefolgt von "None". print() ist nicht nutzlos

4voto

2.7182818 Punkte 122

Mein 2-Cent-Stück:

import sys, traceback
try: 
  ...
except Exception, e:
  T, V, TB = sys.exc_info()
  print ''.join(traceback.format_exception(T,V,TB))

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