2009-08-14 14 views
158

Catching wyjątek, który drukuje tak:Python Kiedy wychwycę wyjątek, w jaki sposób mogę uzyskać typ, plik i numer linii?

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

chcę sformatować go do:

ZeroDivisonError, tmp.py, 1 
+3

pomocą wbudowanego [traceback] (http://docs.python.org/library/traceback.html) moduł. –

+0

Pomocne może być również wydrukowanie wiersza kodu, gdzie wystąpił wyjątek: zobacz http://stackoverflow.com/questions/14519177/python-exception-handling-line-number/20264059#20264059 – Apogentus

Odpowiedz

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

Powinieneś być ostrożny przy rozpakowywaniu sys .exc_info() na zmienne lokalne, ponieważ jeśli otrzymasz wyjątek w procedurze obsługi z wyjątkiem, lokalne zmienne mogą być przechowywane w odwołaniach cyklicznych, a nie w GC. Najlepiej jest zawsze używać plasterków off sys.exc_info(). Lub użyj innych modułów, takich jak traceback, jak sugerowały inne plakaty. –

+1

jest tb tylko exc_tb? i os.path.split (blabla) [1] to os.path.basename (balbal) – sunqiang

+14

Czy to wątek bezpieczne? – RobM

34

Source (Py v2.7.3) dla traceback.format_exception() i nazywa/funkcje związane pomaga bardzo. Żenująco, zawsze zapominam o Read the Source. Zrobiłem to tylko po tym, szukając podobnych szczegółów na próżno. Proste pytanie: "Jak odtworzyć to samo wyjście w Pythonie z wyjątkiem tych samych szczegółów?" To dostanie każdego 90 +% do tego, czego szukają. Sfrustrowany, wymyśliłem ten przykład. Mam nadzieję, że pomoże to innym. (To na pewno pomogło mi ;-)

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 

W konkretnej odpowiedzi na to zapytanie:

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

@atatjuan: 43 linie, nie 50. I to wliczając w to moje nieuzasadnione odstępy i obfite notatki ... chyba że naprawdę byłeś szczęśliwy, to było "tylko 50", w którym to przypadku może być "znacznie krótszy" ... ? :> – pythonlarry

15

Oto przykład pokazujący liczbę linii, gdzie wyjątek ma miejsce.

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

Najprostsza forma, która sprawdziła się u mnie.

import traceback 

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

wyjściowy

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 proste, podoba mi się. – loneRanger

Powiązane problemy