2010-03-01 19 views
17

Cuando ocurre una excepción en Python, ¿puedes inspeccionar la pila? ¿Puedes determinar su profundidad? Miré el módulo traceback, pero no sé cómo usarlo.¿Cómo se puede inspeccionar mediante programación el seguimiento de la pila de una excepción en Python?

Mi objetivo es detectar cualquier excepción que ocurra durante el análisis de una expresión eval, sin capturar excepciones lanzadas por ninguna función que pueda haber llamado. No me regañes por usar eval. No fue mi decisión.

NOTA: deseo hacer esto programáticamente, no interactivamente.

Respuesta

13

traceback es suficiente, y supongo que la documentación lo describe bastante bien. Ejemplo simplificado:

import sys 
import traceback 

try: 
    eval('a') 
except NameError: 
    traceback.print_exc(file=sys.stdout) 
+2

No estoy intentando imprimir la trazabilidad. Estoy tratando de inspeccionarlo. ¿Cómo me dice esto si la excepción ocurrió en el texto eval mismo o en una función llamada por el texto evaluado? –

+0

SyntaxError se lanzará si el texto 'eval' es incorrecto. –

+0

Se pueden generar muchos tipos diferentes de errores si el texto eval es incorrecto.Terminé usando inspeccionar y mirando la profundidad del rastreo para ver si el error fue causado al evaluar el texto original, o si estaba en el cuerpo de una función llamada. –

0

Además de la respuesta de AndiDog sobre inspect, tenga en cuenta que pdb le permite navegar hacia arriba y abajo de la pila, la inspección de los locales y tales cosas. La fuente en la biblioteca estándar pdb.py podría serle útil para aprender cómo hacer tales cosas.

4

Me gusta el módulo de rastreo.

Puede obtener un objeto de rastreo utilizando sys.exc_info(). Luego puede usar ese objeto para obtener una lista preprocesada lista de entradas de rastreo usando traceback.extract_tb(). Entonces se puede obtener una lista legible usando traceback.format_list() de la siguiente manera:

import sys 
import traceback, inspect 

try: 
    f = open("nonExistant file",'r') 
except: 
    (exc_type, exc_value, exc_traceback) = sys.exc_info() 
    #print exception type 
    print exc_type 
    tb_list = traceback.extract_tb(sys.exc_info()[2]) 
    tb_list = traceback.format_list(tb_list) 
    for elt in tb_list: 
     print elt 
     #Do any processing you need here. 

vea el módulo sys: http://docs.python.org/library/sys.html

y el módulo de rastreo: http://docs.python.org/library/traceback.html

1

Se define una función de este tipo():

def raiseErr(): 
    for f in inspect.stack(): print '-', inspect.getframeinfo(f[0]) 

y llámalo desde tus módulos para que:

raiseErr() 

La función raiseErr imprimirá información sobre el lugar donde lo llamó.

más elaborado, puede hacerlo:

import inspect, traceback 
A = [inspect.getframeinfo(f[0]) for f in inspect.stack()] 
print "traceback structure fields:", filter(lambda s: s[0] != '_', dir(A[0])) 
print A[0].filename, A[0].lineno 
for f in inspect.stack(): 
    F = inspect.getframeinfo(f[0]) 
    print '-', F.filename, F.lineno, '\t', F.code_context[0].strip() 

Otra posibilidad es definir esta función:

def tr(): 
    print '* - '*10, 
    print sys._getframe(1).f_code.co_name 

y lo llaman en el lugar donde desea que el rastro. Si quiere toda la traza, cree un iterador desde 1 en _getframe(1).

Cuestiones relacionadas