2011-06-05 5 views
21

A veces, mientras estoy depurando, se genera una excepción.¿Cómo puedo ver los detalles de una excepción en el depurador de Python?

Por ejemplo, considere este código:

def some_function(): # Pretend this function is in a library... 
    # ...and deep within the library is an exception: 
    raise Exception('An exception message with valuable information.') 

import pdb; pdb.set_trace() 
try: 
    some_function() # Pretend I am debugging from this point using pdb. 
except: 
    pass 

Mientras que la depuración de la llamada some_function(), si emite un comando next voy a ver los siguientes detalles acerca de la excepción que se planteó [y atrapó]:

Exception: Exceptio...ation.',) 

Aquí es una copia recta/pegar desde el terminal estaba trabajando en:

> /tmp/test.py(7)<module>() 
-> some_function() # Pretend I am debugging from this point using pdb. 
(Pdb) next 
Exception: Exceptio...ation.',) 
> /tmp/test.py(7)<module>() 
-> some_function() # Pretend I am debugging from this point using pdb. 
(Pdb) 

Sería útil ver el mensaje de excepción completo. ¿Cómo puedo hacer esto en pdb?

+0

¿Qué versión de Python estás usando? El mío no se trunca así. – Keith

+0

Versión 2.7.1. Tenga en cuenta que la declaración de aumento está impresa en su totalidad, por lo que a primera vista puede pensar que toda la excepción está impresa, pero cuando la Excepción real es "interceptada" (no conozco el término) por pdb, se trunca. – Buttons840

+0

Bueno, en realidad escribí mi propia variación de un depurador de Python que no hace eso, y también significa ingresar el depurador automáticamente (usa sys.excepthook). Si lo desea, puede intentarlo en su lugar. Es el subpaquete [depurador] (http://code.google.com/p/pycopia/source/browse/#svn%2Ftrunk%2Fdebugger). – Keith

Respuesta

19

pdb almacena el tipo de excepción y valor en __exception__. Puede imprimir la parte excepción de un rastreo en pdb con:

import traceback; print "".join(traceback.format_exception_only(*__exception__)) 

Por ejemplo:

> /tmp/test.py(7)<module>() 
-> some_function() # Pretend I am debugging from this point using pdb. 
(Pdb) next 
Exception: Exceptio...ation.',) 
> /tmp/test.py(7)<module>() 
-> some_function() # Pretend I am debugging from this point using pdb. 
(Pdb) import traceback; print "".join(traceback.format_exception_only(*__exception__)) 
Exception: An exception message with valuable information. 

(Pdb) 

Desafortunadamente esto no incluye el resto de la traza, pero toda esa información está disponible a través de la where comando de pdb de todos modos. Si realmente desea que el rastreo completo, se puede añadir lo siguiente a su archivo ~/.pdbrc o pegarlo en su terminal:

!global __currentframe, __stack; from inspect import currentframe as __currentframe, stack as __stack 
!global __format_exception_only, __print_stack; from traceback import format_exception_only as __format_exception_only, print_stack as __print_stack 
!global __Pdb; from pdb import Pdb as __Pdb 

# find the last frame on the stack with an object named "pdb" or "self" that is a pdb.Pdb object 
# works for pdb called the usual way, or pdb.pm(), or pdb.set_trace() 
!global __pdb; __pdb = [__framerec[0].f_locals.get("pdb") or __framerec[0].f_locals.get("self") for __framerec in __stack() if (__framerec[0].f_locals.get("pdb") or __framerec[0].f_locals.get("self")).__class__ == __Pdb][-1] 

alias traceback __print_stack(__pdb.stack[-1][0]); print "".join(__format_exception_only(*__exception__)) 

continuación, sólo puede utilizar las nuevas traceback alias para obtener lo que desea:

> /tmp/test.py(7)<module>() 
-> some_function() # Pretend I am debugging from this point using pdb. 
(Pdb) next 
Exception: Exceptio...ation.',) 
> /tmp/test.py(7)<module>() 
-> some_function() # Pretend I am debugging from this point using pdb. 
(Pdb) traceback 
    File "test.py", line 7, in <module> 
    some_function() # Pretend I am debugging from this point using pdb. 
    File "test.py", line 3, in some_function 
    raise Exception('An exception message with valuable information.') 
Exception: An exception message with valuable information. 

(Pdb) 

Advertencia: todo esto depende de pdb indocumentado y bdb partes internas y es probable que se rompa.

+0

Gracias por el truco extremadamente útil. Es decepcionante que no haya una forma normal de hacer algo tan común y útil. Este truco también funciona con pdb ++, así que voy a cambiarlo por 'ipdb'. – DBedrenko

6

El depurador de python no "rompe con la excepción", lo que puede ser bastante frustrante si está acostumbrado a esa funcionalidad. Como tal, adopto una política de registro de trazas y trabajo desde allí.

import logging 
try: 
    raise Exception('An exception message with valuable information.') 
except: 
    logging.exception('Error in test code') 

Si utiliza un buen IDE (como Eclipse con pydev), las entradas del registro para el StackTrace se convierten en enlaces que saltar directamente a la posición apropiada en el código.

se puede volcar un seguimiento de pila en cualquier punto de su código de rastreo mediante la importación de

import traceback 
trace = traceback.format_exc() 
+2

Es mejor usar 'logging.excepción ('Mensaje informativo') 'que registra la trazabilidad de excepción, y también cualquier información sobre la operación que falló (el 'mensaje informativo', que puede tener argumentos, etc.). Puede iniciar sesión en cualquier nivel (por ejemplo, DEPURAR) usando 'logging.debug (..., exc_info = True)'. –

+0

No era consciente de eso, gracias Vinay. ¿Actualizaré mi respuesta si eso está bien? –

+0

Estoy usando twisted.python.log. Podría usar el registro, pero preferiría no hacerlo. Además, el intento: raise; excepto: ... no está en mi código sino en algún lugar en retorcido, (al menos eso creo). Entonces, si voy a usar el registro de esa manera, tendré que modificar el código retorcido. – Buttons840

Cuestiones relacionadas