2009-08-14 8 views
158

La captura de una excepción que imprimiría la siguiente manera:Python Cuando encuentro una excepción, ¿cómo obtengo el tipo, archivo y número de línea?

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

Quiero darle formato en:

ZeroDivisonError, tmp.py, 1 
+3

Utilice el módulo integrado [rastreo] (http://docs.python.org/library/traceback.html). –

+0

También puede ser útil imprimir una línea de código, donde ocurrió la excepción: vea http://stackoverflow.com/questions/14519177/python-exception-handling-line-number/20264059#20264059 – Apogentus

Respuesta

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

Debe tener cuidado al desempaquetar el sistema .exc_info() en variables locales, ya que si obtienes una excepción en el controlador except, las variables locales podrían mantenerse en una referencia circular y no en GC'd. La mejor práctica es usar siempre segmentos de sys.exc_info() en su lugar. O use otros módulos como traceback, como han sugerido otros carteles. –

+1

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

+14

¿Esto es seguro para subprocesos? – RobM

34

Source (Py v2.7.3) para traceback.format_exception() y llamada/funciones relacionadas con la ayuda muy. A vergüenza, siempre me olvido de Read the Source. Solo lo hice después de buscar detalles similares en vano. Una pregunta simple, "¿Cómo recrear el mismo resultado que Python para una excepción, con todos los mismos detalles?" Esto le daría a cualquiera 90 +% de lo que sea que esté buscando. Frustrado, se me ocurrió este ejemplo. Espero que ayude a otros. (Seguro que me ayudó ;-)

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 respuesta específica a esta consulta:

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 líneas, no 50. Y eso incluye mi espacio gratuito y notas copiosas ... a menos que realmente estés contento de que sea "solo 50", en cuyo caso se puede hacer que sea "mucho más corto" ... ? :> – pythonlarry

15

Aquí se muestra un ejemplo de mostrar el número de línea donde se produce una excepción.

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

Forma más simple que funcionó para mí.

import traceback 

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

salida

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, me gusta. – loneRanger

Cuestiones relacionadas