Holen Sie sich Ausnahmebeschreibung und Stapelverfolgung, was eine Ausnahme verursachte, alles als Zeichenfolge

StackOverflow https://stackoverflow.com/questions/4564559

Frage

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

Ich habe einen Stück Python 2.7 -Code, der eine Ausnahme hervorrufen kann. Ich würde es gerne fangen und a zuweisen Saite Die vollständige Beschreibung und die Stapelspur, die den Fehler verursachte (einfach alles, was wir auf der Konsole sehen). Ich brauche diese Zeichenfolge, um sie in ein Textfeld in der GUI zu drucken.

Etwas wie das:

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?

War es hilfreich?

Lösung

Siehe das traceback Modul, insbesondere das format_exc() Funktion. Hier.

import traceback

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

Andere Tipps

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

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

def do_something_that_might_error():
    raise_error()

Protokollieren Sie den vollen Stacktrace

Eine beste Praxis ist, dass ein Logger für Ihr Modul eingerichtet ist. Es wird den Namen des Moduls kennen und in der Lage sein, die Ebenen zu ändern (unter anderem Attribute, 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!

Und so erhalten wir 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 Zeichenfolge bekommen

Wenn Sie wirklich nur die Zeichenfolge wollen, verwenden Sie die traceback.format_exc Funktion stattdessen und demonstrieren Sie die Protokollierung der Zeichenfolge hier:

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!
>>> 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 nutzen sys.exc_info () Um die Informationen und Funktionen in der zu sammeln traceback Modul, um es zu formatieren.Hier sind einige Beispiele für die Formatierung.

Die gesamte Ausnahmezeichenfolge 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']

Mit Python 3 formatiert der folgende Code eine Exception Objekt genau wie mit Verwendung erhalten würde 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__)))

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

Für diejenigen, die verwenden Python-3

Verwendung traceback Modul und exception.__traceback__ Man kann die Stapel-Trace wie folgt extrahieren:

  • Packe die aktuell Stack-Trace Verwenden traceback.extract_stack()
  • Entfernen Sie die letzten drei Elemente (da dies Einträge im Stapel sind, die mich zu meiner Debug -Funktion gebracht haben)
  • append der __traceback__ Aus dem Ausnahmebobjekt verwendet traceback.extract_tb()
  • Formatieren Sie das Ganze mit Verwendung 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 anrufen 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

Sie können auch das eingebaute Python-Modul in Betracht ziehen. 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)

Wir erhalten 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

Wenn Sie dieselben Informationen erhalten möchten, wenn eine Ausnahme nicht behandelt wird, können Sie so etwas tun. Tun import traceback und dann:

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

Ich benutze Python 3.7.

meine 2 Cents:

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

Ich habe die folgende Helferklasse definiert:

import traceback
class TracedExeptions(object):
    def __init__(self):
        pass
    def __enter__(self):
        pass

    def __exit__(self, etype, value, tb):
      if value :
        if not hasattr(value, 'traceString'):
          value.traceString = "\n".join(traceback.format_exception(etype, value, tb))
        return False
      return True

Was ich später so verwenden kann:

with TracedExeptions():
  #some-code-which-might-throw-any-exception

Und später kann es so konsumieren:

def log_err(ex):
  if hasattr(ex, 'traceString'):
    print("ERROR:{}".format(ex.traceString));
  else:
    print("ERROR:{}".format(ex));

(Hintergrund: Ich war wegen der Verwendung frustriert Promises zusammen mit Exceptions, was leider an einem Ort an einem Ort an einen Ort an einem anderen Ort an einem Ort angehoben wird, und daher ist es schwierig, das Traceback vom ursprünglichen Standort aus zu erhalten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top