2009-08-14 7 views
158

Attraper une exception qui imprimerait comme ceci:Python Lorsque j'attrape une exception, comment obtenir le type, le fichier et le numéro de ligne?

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

Je veux formater dans:

ZeroDivisonError, tmp.py, 1 
+3

Utilisez le module intégré [traceback] (http://docs.python.org/library/traceback.html). –

+0

Il peut également être utile d'imprimer une ligne de code, où l'exception s'est produite: voir http://stackoverflow.com/questions/14519177/python-exception-handling-line-number/20264059#20264059 – Apogentus

Répondre

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

Vous devez faire attention au déballage du système .exc_info() dans les variables locales, car si vous obtenez une exception dans le gestionnaire except, les variables locales peuvent être conservées dans une référence circulaire et non GC'd. La meilleure pratique consiste à toujours utiliser simplement les tranches de sys.exc_info() à la place. Ou utilisez d'autres modules comme le retraçage, comme d'autres affiches l'ont suggéré. –

+1

est tb juste exc_tb? et os.path.split (blabla) [1] est os.path.basename (balbal) – sunqiang

+14

Est-ce thread-safe? – RobM

34

Source (Py v2.7.3) pour traceback.format_exception() et fonctions appelées/connexes aide très. Embarrassant, j'oublie toujours à Read the Source. Je ne l'ai fait que pour cela après avoir recherché des détails similaires en vain. Une question simple, "Comment recréer la même sortie que Python pour une exception, avec tous les mêmes détails?" Cela permettrait à tout le monde 90 +% à tout ce qu'ils cherchent. Frustré, je suis venu avec cet exemple. J'espère que ça aide les autres. (Il vous m'a aidé ;-)

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 

En réponse spécifique à cette question:

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 lignes, pas 50. Et cela inclut mes espacements gratuits et mes notes copieuses ... à moins que vous n'ayez vraiment été heureux, c'était "seulement 50", auquel cas il peut être fait "beaucoup plus court" ... ? :> – pythonlarry

15

Voici un exemple de montrer le numéro de ligne où exception a lieu.

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

Forme la plus simple qui a fonctionné pour moi.

import traceback 

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

sortie

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 simple, j'aime ça. – loneRanger

Questions connexes