2009-08-14 10 views
158

Facendo un'eccezione che la stampa in questo modo:Python Quando rilevo un'eccezione, come ottengo il tipo, il file e il numero di riga?

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

voglio formattarlo in:

ZeroDivisonError, tmp.py, 1 
+3

Utilizzare il modulo built-in [traceback] (http://docs.python.org/library/traceback.html). –

+0

Potrebbe anche essere utile stampare la riga di codice, dove si è verificata un'eccezione: consultare http://stackoverflow.com/questions/14519177/python-exception-handling-line-number/20264059#20264059 – Apogentus

risposta

239
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) 
+32

È necessario fare attenzione a decomprimere il sistema .exc_info() in variabili locali, poiché se si ottiene un'eccezione nel gestore tranne, le variabili locali potrebbero essere mantenute in un riferimento circolare e non in GC. La migliore pratica è quella di utilizzare sempre solo le slice al di fuori di sys.exc_info(). Oppure usa altri moduli come traceback, come suggerito da altri poster. –

+1

è tb solo exc_tb? e os.path.split (blabla) [1] è os.path.basename (balbal) – sunqiang

+14

È questo thread-safe? – RobM

34

Source (Py v2.7.3) per traceback.format_exception() e chiamata/funzioni relative aiuta notevolmente. In modo imbarazzante, mi dimentico sempre di Read the Source. L'ho fatto solo per questo dopo aver cercato invano dettagli simili. Una semplice domanda, "Come ricreare lo stesso risultato di Python per un'eccezione, con tutti gli stessi dettagli?" Ciò porterebbe chiunque al 90% in più a qualsiasi cosa stiano cercando. Frustrato, ho trovato questo esempio. Spero che aiuti gli altri. (E 'sicuro che mi ha aiutato ;-)

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 risposta specifica a questa domanda:

sys.exc_info()[0].__name__, os.path.basename(sys.exc_info()[2].tb_frame.f_code.co_filename), sys.exc_info()[2].tb_lineno 
+2

@thatjuan: 43 righe, non 50. E questo include la mia spaziatura gratuita e note abbondanti ... a meno che tu non sia stato davvero contento fosse "solo 50", nel qual caso si può essere "molto più brevi" ... ? :> – pythonlarry

15

Ecco un esempio di mostrare il numero di riga in cui si svolge eccezione.

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') 
5

La forma più semplice che ha funzionato per me.

import traceback 

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

uscita

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 
+1

super semplice, mi piace. – loneRanger

Problemi correlati