Wie erhalte ich den Typ, die Datei und die Zeilennummer, wenn ich eine Ausnahme abfange?

250

Eine Ausnahme abfangen, die wie folgt gedruckt wird:

Traceback (most recent call last):
  File "c:/tmp.py", line 1, in <module>
    4 / 0
ZeroDivisionError: integer division or modulo by zero

Ich möchte es formatieren in:

ZeroDivisonError, tmp.py, 1
Claudiu
quelle
5
Verwenden Sie das integrierte Traceback- Modul.
Ned Deily
Es kann auch hilfreich sein, eine Codezeile zu drucken, wenn eine Ausnahme aufgetreten
Apogentus

Antworten:

380
import sys, os

try:
    raise NotImplementedError("No error")
except Exception as e:
    exc_type, exc_obj, exc_tb = sys.exc_info()
    fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
    print(exc_type, fname, exc_tb.tb_lineno)
Ameisen Aasma
quelle
51
Sie sollten vorsichtig sein, wenn Sie sys.exc_info () in lokale Variablen entpacken, da die lokalen Variablen in einer Zirkelreferenz und nicht in einer GC-Datei gespeichert werden können, wenn Sie im Ausnahme-Handler eine Ausnahme erhalten. Es wird empfohlen, stattdessen immer nur Slices aus sys.exc_info () zu verwenden. Oder verwenden Sie andere Module wie Traceback, wie andere Poster vorgeschlagen haben.
Daniel Pryden
1
ist tb nur exc_tb? und os.path.split (blabla) [1] ist os.path.basename (balbal)
sunqiang
4
@Basj: Mit sys.exc_info () [0] .__ name__ erhalten Sie den einfachen Namen des Typs.
Johannes Overmann
5
@ DanielPryden Python-Dokumente verwenden auch die gleiche Entpackungsmethode docs.python.org/2/library/traceback.html#traceback-examples
Benutzer
3
@RobM: Ja, es ist threadsicher. sys.exc_info()wurde eingeführt, um Thread-Sicherheitsprobleme in der vorherigen API zu beheben. Die Ausgabe ist sowohl für den aktuellen Thread als auch für den aktuellen Stapelrahmen spezifisch.
user2357112 unterstützt Monica
125

Einfachste Form, die für mich funktioniert hat.

import traceback

try:
    print(4/0)
except ZeroDivisionError:
    print(traceback.format_exc())

Ausgabe

Traceback (most recent call last):
  File "/path/to/file.py", line 51, in <module>
    print(4/0)
ZeroDivisionError: division by zero

Process finished with exit code 0
nu everest
quelle
7
Dies ist zwar nicht genau das gewünschte Format, aber die einfachste und robusteste Lösung
cs_alumnus
5
Was ist daran robust?
Jouell
1
@jouell Hey, ich benutze manchmal auch gerne ausgefallene Wörter :)
Rishav
Sauber und effektiv. Danke fürs Teilen :)
Himanshu Gautam
49

Die Quelle (Py v2.7.3) für traceback.format_exception () und aufgerufene / verwandte Funktionen hilft sehr. Peinlicherweise vergesse ich immer, die Quelle zu lesen . Ich habe dies nur getan, nachdem ich vergeblich nach ähnlichen Details gesucht hatte. Eine einfache Frage: "Wie kann ich für eine Ausnahme dieselbe Ausgabe wie Python mit denselben Details neu erstellen?" Dies würde jedem 90 +% zu dem bringen, wonach er sucht. Frustriert kam ich auf dieses Beispiel. Ich hoffe es hilft anderen. (Es hat mir sicher geholfen! ;-)

import sys, traceback

traceback_template = '''Traceback (most recent call last):
  File "%(filename)s", line %(lineno)s, in %(name)s
%(type)s: %(message)s\n''' # Skipping the "actual line" item

# Also note: we don't walk all the way through the frame stack in this example
# see hg.python.org/cpython/file/8dffb76faacc/Lib/traceback.py#l280
# (Imagine if the 1/0, below, were replaced by a call to test() which did 1/0.)

try:
    1/0
except:
    # http://docs.python.org/2/library/sys.html#sys.exc_info
    exc_type, exc_value, exc_traceback = sys.exc_info() # most recent (if any) by default

    '''
    Reason this _can_ be bad: If an (unhandled) exception happens AFTER this,
    or if we do not delete the labels on (not much) older versions of Py, the
    reference we created can linger.

    traceback.format_exc/print_exc do this very thing, BUT note this creates a
    temp scope within the function.
    '''

    traceback_details = {
                         'filename': exc_traceback.tb_frame.f_code.co_filename,
                         'lineno'  : exc_traceback.tb_lineno,
                         'name'    : exc_traceback.tb_frame.f_code.co_name,
                         'type'    : exc_type.__name__,
                         'message' : exc_value.message, # or see traceback._some_str()
                        }

    del(exc_type, exc_value, exc_traceback) # So we don't leave our local labels/objects dangling
    # This still isn't "completely safe", though!
    # "Best (recommended) practice: replace all exc_type, exc_value, exc_traceback
    # with sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]

    print
    print traceback.format_exc()
    print
    print traceback_template % traceback_details
    print

In konkreter Antwort auf diese Frage:

sys.exc_info()[0].__name__, os.path.basename(sys.exc_info()[2].tb_frame.f_code.co_filename), sys.exc_info()[2].tb_lineno
Pythonlarry
quelle
1
ändern Sie 'message' : exc_value.messagefür 'message' : str(exc_value)für py3
user2682863
34

Hier ist ein Beispiel für die Anzeige der Zeilennummer, in der eine Ausnahme auftritt.

import sys
try:
    print(5/0)
except Exception as e:
    print('Error on line {}'.format(sys.exc_info()[-1].tb_lineno), type(e).__name__, e)

print('And the rest of program continues')
Stryker
quelle