web-dev-qa-db-de.com

Wie kann ich Traceback/sys.exc_info () Werte in einer Variablen speichern?

Ich möchte den Namen des Fehlers und die Traceback-Details in einer Variablen speichern. Hier ist mein Versuch.

import sys
try:
    try:
        print x
    except Exception, ex:
        raise NameError
except Exception, er:
    print "0", sys.exc_info()[0]
    print "1", sys.exc_info()[1]
    print "2", sys.exc_info()[2]

Ausgabe:

0 <type 'exceptions.NameError'>
1 
2 <traceback object at 0xbd5fc8>

Gewünschte Ausgabe:

0 NameError
1
2 Traceback (most recent call last):
  File "exception.py", line 6, in <module>
    raise NameError

P.S. Ich weiß, dass dies mit dem Traceback-Modul problemlos möglich ist, aber ich möchte hier die Verwendung des Objekts sys.exc_info () [2] kennen.

90
codersofthedark

So mache ich es:

>>> import traceback
>>> try:
...   int('k')
... except:
...   var = traceback.format_exc()
... 
>>> print var
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ValueError: invalid literal for int() with base 10: 'k'

Sie sollten sich jedoch die traceback-Dokumentation anschauen, da es möglicherweise geeignetere Methoden gibt, je nachdem, wie Sie Ihre Variable anschließend bearbeiten möchten ...

126
mac

sys.exc_info () gibt ein Tuple mit drei Werten (type, value, traceback) zurück. 

  1. Hier erhält type den Ausnahmetyp der behandelten Exception
  2. value sind die Argumente, die an den Konstruktor der Ausnahmeklasse übergeben werden  
  3. traceback enthält die Stack-Informationen, z. B. wo die Ausnahme aufgetreten ist usw.

Zum Beispiel im folgenden Programm

try:

    a = 1/0

except Exception,e:

    exc_Tuple = sys.exc_info()

Wenn wir nun den Tupel drucken, werden dies die Werte sein.

  1. exc_Tuple [0] -Wert ist " ZeroDivisionError "
  2. exc_Tuple [1] -Wert ist " Ganzzahldivision oder Modulo durch Null " (String, der der Ausnahmeklasse als Parameter übergeben wird)
  3. exc_Tuple [2] -Wert ist " Trackback-Objekt um (einige Speicheradresse) "

Die obigen Details können auch abgerufen werden, indem die Ausnahme einfach im Zeichenfolgenformat gedruckt wird. 

print str(e)
18
keya

Verwenden Sie traceback.extract_stack(), wenn Sie bequem auf Modulnamen, Funktionsnamen und Leitungsnummern zugreifen möchten.

Verwenden Sie ''.join(traceback.format_stack()), wenn Sie nur eine Zeichenfolge wünschen, die wie die Ausgabe von traceback.print_stack() aussieht.

Beachten Sie, dass Sie auch mit ''.join() einen mehrzeiligen String erhalten, da die Elemente von format_stack()\n enthalten. Siehe Ausgabe unten.

Denken Sie an import traceback.

Hier ist die Ausgabe von traceback.extract_stack(). Formatierung zur besseren Lesbarkeit hinzugefügt.

>>> traceback.extract_stack()
[
   ('<string>', 1, '<module>', None),
   ('C:\\Python\\lib\\idlelib\\run.py', 126, 'main', 'ret = method(*args, **kwargs)'),
   ('C:\\Python\\lib\\idlelib\\run.py', 353, 'runcode', 'exec(code, self.locals)'),
   ('<pyshell#1>', 1, '<module>', None)
]

Hier ist die Ausgabe von ''.join(traceback.format_stack()). Formatierung zur besseren Lesbarkeit hinzugefügt.

>>> ''.join(traceback.format_stack())
'  File "<string>", line 1, in <module>\n
   File "C:\\Python\\lib\\idlelib\\run.py", line 126, in main\n
       ret = method(*args, **kwargs)\n
   File "C:\\Python\\lib\\idlelib\\run.py", line 353, in runcode\n
       exec(code, self.locals)\n  File "<pyshell#2>", line 1, in <module>\n'
16
Nathan

Seien Sie vorsichtig, wenn Sie das Exception-Objekt oder das Traceback-Objekt aus dem Exception-Handler entfernen, da dies zu Zirkelverweisen führt und gc.collect() das Sammeln nicht durchführen kann. Dies scheint ein besonderes Problem in der Notebook-Umgebung ipython/jupyter zu sein, bei dem das Traceback-Objekt nicht zur richtigen Zeit gelöscht wird und selbst ein expliziter Aufruf von gc.collect() im Abschnitt finally nichts bewirkt. Und das ist ein riesiges Problem, wenn Sie einige große Objekte haben, deren Speicher dadurch nicht wiederhergestellt werden (z. B. CUDA hat nicht genügend Arbeitsspeicher, mit Ausnahme, dass diese Lösung keinen vollständigen Kernel-Neustart erfordert, um wiederhergestellt zu werden).

Wenn Sie das Traceback-Objekt speichern möchten, müssen Sie es in der Regel aus den Verweisen auf locals() entfernen.

import sys, traceback, gc
type, val, tb = None, None, None
try:
    myfunc()
except:
    type, val, tb = sys.exc_info()
    traceback.clear_frames(tb)
# some cleanup code
gc.collect()
# and then use the tb:
if tb:
    raise type(val).with_traceback(tb)

Im Fall eines Jupyter-Notebooks müssen Sie dies zumindest im Ausnahmehandler tun:

try:
    myfunc()
except:
    type, val, tb = sys.exc_info()
    traceback.clear_frames(tb)
    raise type(val).with_traceback(tb)
finally:
    # cleanup code in here
    gc.collect()

Getestet mit Python 3.7.

p.s. Das Problem mit ipython oder jupyter notebook env ist, dass es %tb magic hat, das den Traceback speichert und später wieder verfügbar macht. Daher wird jede locals() in allen an dem Traceback beteiligten Frames nicht freigegeben, bis das Notebook beendet wird oder eine andere Ausnahme die zuvor gespeicherte Rückverfolgung überschreibt. Das ist sehr problematisch. Es sollte das Traceback nicht speichern, ohne seine Frames zu säubern. Fix eingereicht hier .

1
stason

Das Objekt kann als Parameter in der Funktion Exception.with_traceback() verwendet werden:

except Exception as e:
    tb = sys.exc_info()
    print(e.with_traceback(tb[2]))
0
Hansen D'Silva