traceback — Excepciones y rastreos de pila¶
Propósito: | Extraer, formatear e imprimir excepciones y rastreos de pila. |
---|
El módulo traceback
funciona con la pila de llamadas para generar mensajes
de error. Un traceback es un seguimiento de la pila desde el punto de un
controlador de excepciones en la cadena de llamadas hasta el punto donde se
generó la excepción. También se puede acceder a los rastreos desde la pila de
llamadas actual desde el punto de una llamada (y sin el contexto de un error),
lo cual es útil para descubrir las rutas que se siguen en una función.
La interfaz de programación de alto nivel en traceback
usa instancias
StackSummary
y FrameSummary
para mantener la representación de la pila.
Estas clases pueden construirse a partir de un rastreo o la pila de ejecución
actual, y luego procesarse de la misma manera.
Las funciones de bajo nivel en traceback
se dividen en varias categorías
comunes. Hay funciones para extraer rastreos sin procesar del entorno de
tiempo de ejecución actual (ya sea un controlador de excepción para un rastreo
o la pila normal). El rastreo de pila extraída es una secuencia de tuplas que
contiene el nombre de archivo, el número de línea, el nombre de la función y el
texto de la línea de origen.
Una vez extraído, el rastreo de la pila se puede formatear usando funciones
como format_exception()
, format_stack()
, etc. Las funciones de formato
devuelven una lista de cadenas con mensajes formateados para ser impresos.
También hay funciones abreviadas para imprimir los valores formateados.
Aunque las funciones en traceback
imitan el comportamiento del intérprete
interactivo de forma predeterminada, también son útiles para manejar
excepciones en situaciones en las que no es deseable descargar el rastreo
completo de la pila en la consola. Por ejemplo, una aplicación web puede
necesitar formatear el rastreo para que se vea bien en HTML y un IDE puede
convertir los elementos del rastreo de la pila en una lista en la que se puede
hacer clic para que el usuario explore la fuente.
Funciones de apoyo¶
Los ejemplos en esta sección usan el módulo traceback_example.py
.
import traceback
import sys
def produce_exception(recursion_level=2):
sys.stdout.flush()
if recursion_level:
produce_exception(recursion_level - 1)
else:
raise RuntimeError()
def call_function(f, recursion_level=2):
if recursion_level:
return call_function(f, recursion_level - 1)
else:
return f()
Examinar la pila¶
Para examinar la pila actual, construye un StackSummary
a partir de
walk_stack()
.
import traceback
import sys
from traceback_example import call_function
def f():
summary = traceback.StackSummary.extract(
traceback.walk_stack(None)
)
print(''.join(summary.format()))
print('Calling f() directly:')
f()
print()
print('Calling f() from 3 levels deep:')
call_function(f)
El método format()
produce una secuencia de cadenas formateadas listas para
imprimir.
$ python3 traceback_stacksummary.py
Calling f() directly:
File "traceback_stacksummary.py", line 18, in f
traceback.walk_stack(None)
File "traceback_stacksummary.py", line 24, in <module>
f()
Calling f() from 3 levels deep:
File "traceback_stacksummary.py", line 18, in f
traceback.walk_stack(None)
File ".../traceback_example.py", line 26, in call_function
return f()
File ".../traceback_example.py", line 24, in call_function
return call_function(f, recursion_level - 1)
File ".../traceback_example.py", line 24, in call_function
return call_function(f, recursion_level - 1)
File "traceback_stacksummary.py", line 28, in <module>
call_function(f)
El StackSummary
es un contenedor iterable que contiene instancias de
FrameSummary
.
import traceback
import sys
from traceback_example import call_function
template = (
'{fs.filename:<26}:{fs.lineno}:{fs.name}:\n'
' {fs.line}'
)
def f():
summary = traceback.StackSummary.extract(
traceback.walk_stack(None)
)
for fs in summary:
print(template.format(fs=fs))
print('Calling f() directly:')
f()
print()
print('Calling f() from 3 levels deep:')
call_function(f)
Cada FrameSummary
describe un marco de la pila, que incluye información
sobre dónde está el contexto de ejecución en los archivos fuente del programa.
$ python3 traceback_framesummary.py
Calling f() directly:
traceback_framesummary.py :23:f:
traceback.walk_stack(None)
traceback_framesummary.py :30:<module>:
f()
Calling f() from 3 levels deep:
traceback_framesummary.py :23:f:
traceback.walk_stack(None)
.../traceback_example.py:26:call_function:
return f()
.../traceback_example.py:24:call_function:
return call_function(f, recursion_level - 1)
.../traceback_example.py:24:call_function:
return call_function(f, recursion_level - 1)
traceback_framesummary.py :34:<module>:
call_function(f)
TracebackException¶
La clase TracebackException
es una interfaz de alto nivel para construir un
StackSummary
mientras se procesa un rastreo.
import traceback
import sys
from traceback_example import produce_exception
print('with no exception:')
exc_type, exc_value, exc_tb = sys.exc_info()
tbe = traceback.TracebackException(exc_type, exc_value, exc_tb)
print(''.join(tbe.format()))
print('\nwith exception:')
try:
produce_exception()
except Exception as err:
exc_type, exc_value, exc_tb = sys.exc_info()
tbe = traceback.TracebackException(
exc_type, exc_value, exc_tb,
)
print(''.join(tbe.format()))
print('\nexception only:')
print(''.join(tbe.format_exception_only()))
El método format()
produce una versión formateada del rastreo completo,
mientras que format_exception_only()
muestra solo el mensaje de excepción.
$ python3 traceback_tracebackexception.py
with no exception:
None: None
with exception:
Traceback (most recent call last):
File "traceback_tracebackexception.py", line 22, in <module>
produce_exception()
File ".../traceback_example.py", line 17, in produce_exception
produce_exception(recursion_level - 1)
File ".../traceback_example.py", line 17, in produce_exception
produce_exception(recursion_level - 1)
File ".../traceback_example.py", line 19, in produce_exception
raise RuntimeError()
RuntimeError
exception only:
RuntimeError
Interfaz de programación de excepción de bajo nivel¶
Otra forma de manejar los informes de excepción es con print_exc()
. Utiliza
sys.exc_info()
para obtener la información de excepción para el hilo
actual, formatea los resultados e imprime el texto en un identificador de
archivo (sys.stderr
, por defecto).
import traceback
import sys
from traceback_example import produce_exception
print('print_exc() with no exception:')
traceback.print_exc(file=sys.stdout)
print()
try:
produce_exception()
except Exception as err:
print('print_exc():')
traceback.print_exc(file=sys.stdout)
print()
print('print_exc(1):')
traceback.print_exc(limit=1, file=sys.stdout)
En este ejemplo, el identificador de archivo para sys.stdout
se sustituye
para que los mensajes informativos y de rastreo se mezclen correctamente:
$ python3 traceback_print_exc.py
print_exc() with no exception:
NoneType: None
print_exc():
Traceback (most recent call last):
File "traceback_print_exc.py", line 20, in <module>
produce_exception()
File ".../traceback_example.py", line 17, in produce_exception
produce_exception(recursion_level - 1)
File ".../traceback_example.py", line 17, in produce_exception
produce_exception(recursion_level - 1)
File ".../traceback_example.py", line 19, in produce_exception
raise RuntimeError()
RuntimeError
print_exc(1):
Traceback (most recent call last):
File "traceback_print_exc.py", line 20, in <module>
produce_exception()
RuntimeError
print_exc()
es solo un atajo para print_exception()
, que requiere
argumentos explícitos.
import traceback
import sys
from traceback_example import produce_exception
try:
produce_exception()
except Exception as err:
print('print_exception():')
exc_type, exc_value, exc_tb = sys.exc_info()
traceback.print_exception(exc_type, exc_value, exc_tb)
Los argumentos de print_exception()
son producidos por sys.exc_info()
.
$ python3 traceback_print_exception.py
Traceback (most recent call last):
File "traceback_print_exception.py", line 16, in <module>
produce_exception()
File ".../traceback_example.py", line 17, in produce_exception
produce_exception(recursion_level - 1)
File ".../traceback_example.py", line 17, in produce_exception
produce_exception(recursion_level - 1)
File ".../traceback_example.py", line 19, in produce_exception
raise RuntimeError()
RuntimeError
print_exception():
print_exception()
usa format_exception()
para preparar el texto.
import traceback
import sys
from pprint import pprint
from traceback_example import produce_exception
try:
produce_exception()
except Exception as err:
print('format_exception():')
exc_type, exc_value, exc_tb = sys.exc_info()
pprint(
traceback.format_exception(exc_type, exc_value, exc_tb),
width=65,
)
Los mismos tres argumentos, tipo de excepción, valor de excepción y rastreo, se
usan con format_exception()
.
$ python3 traceback_format_exception.py
format_exception():
['Traceback (most recent call last):\n',
' File "traceback_format_exception.py", line 17, in
<module>\n'
' produce_exception()\n',
' File '
'".../traceback_example.py", '
'line 17, in produce_exception\n'
' produce_exception(recursion_level - 1)\n',
' File '
'".../traceback_example.py", '
'line 17, in produce_exception\n'
' produce_exception(recursion_level - 1)\n',
' File '
'".../traceback_example.py", '
'line 19, in produce_exception\n'
' raise RuntimeError()\n',
'RuntimeError\n']
Para procesar el rastreo de alguna otra manera, como formatearlo de manera
diferente, usa extract_tb()
para obtener los datos en una forma utilizable.
import traceback
import sys
import os
from traceback_example import produce_exception
template = '{filename:<23}:{linenum}:{funcname}:\n {source}'
try:
produce_exception()
except Exception as err:
print('format_exception():')
exc_type, exc_value, exc_tb = sys.exc_info()
for tb_info in traceback.extract_tb(exc_tb):
filename, linenum, funcname, source = tb_info
if funcname != '<module>':
funcname = funcname + '()'
print(template.format(
filename=os.path.basename(filename),
linenum=linenum,
source=source,
funcname=funcname)
)
El valor de retorno es una lista de entradas de cada nivel de la pila representada por el rastreo. Cada entrada es una tupla con cuatro partes: el nombre del archivo fuente, el número de línea en ese archivo, el nombre de la función y el texto fuente de esa línea con espacios en blanco despojados (si la fuente está disponible).
$ python3 traceback_extract_tb.py
format_exception():
traceback_extract_tb.py:18:<module>:
produce_exception()
traceback_example.py :17:produce_exception():
produce_exception(recursion_level - 1)
traceback_example.py :17:produce_exception():
produce_exception(recursion_level - 1)
traceback_example.py :19:produce_exception():
raise RuntimeError()
Interfaz de programación de pila de bajo nivel¶
Hay un conjunto similar de funciones para realizar las mismas operaciones con
la pila de llamadas actual en lugar de un rastreo. print_stack()
imprime
la pila actual, sin generar una excepción.
import traceback
import sys
from traceback_example import call_function
def f():
traceback.print_stack(file=sys.stdout)
print('Calling f() directly:')
f()
print()
print('Calling f() from 3 levels deep:')
call_function(f)
El resultado parece un rastreo sin un mensaje de error.
$ python3 traceback_print_stack.py
Calling f() directly:
File "traceback_print_stack.py", line 21, in <module>
f()
File "traceback_print_stack.py", line 17, in f
traceback.print_stack(file=sys.stdout)
Calling f() from 3 levels deep:
File "traceback_print_stack.py", line 25, in <module>
call_function(f)
File ".../traceback_example.py", line 24, in call_function
return call_function(f, recursion_level - 1)
File ".../traceback_example.py", line 24, in call_function
return call_function(f, recursion_level - 1)
File ".../traceback_example.py", line 26, in call_function
return f()
File "traceback_print_stack.py", line 17, in f
traceback.print_stack(file=sys.stdout)
format_stack()
prepara el seguimiento de la pila de la misma manera que
format_exception()
prepara la excepción.
import traceback
import sys
from pprint import pprint
from traceback_example import call_function
def f():
return traceback.format_stack()
formatted_stack = call_function(f)
pprint(formatted_stack)
Devuelve una lista de cadenas, cada una de las cuales constituye una línea de la salida.
$ python3 traceback_format_stack.py
[' File "traceback_format_stack.py", line 21, in <module>\n'
' formatted_stack = call_function(f)\n',
' File '
'".../traceback_example.py", '
'line 24, in call_function\n'
' return call_function(f, recursion_level - 1)\n',
' File '
'".../traceback_example.py", '
'line 24, in call_function\n'
' return call_function(f, recursion_level - 1)\n',
' File '
'".../traceback_example.py", '
'line 26, in call_function\n'
' return f()\n',
' File "traceback_format_stack.py", line 18, in f\n'
' return traceback.format_stack()\n']
La función extract_stack()
funciona como extract_tb()
.
import traceback
import sys
import os
from traceback_example import call_function
template = '{filename:<26}:{linenum}:{funcname}:\n {source}'
def f():
return traceback.extract_stack()
stack = call_function(f)
for filename, linenum, funcname, source in stack:
if funcname != '<module>':
funcname = funcname + '()'
print(template.format(
filename=os.path.basename(filename),
linenum=linenum,
source=source,
funcname=funcname)
)
También acepta argumentos, que no se muestran aquí, para comenzar desde un lugar alternativo en el marco de la pila o para limitar la profundidad del recorrido.
$ python3 traceback_extract_stack.py
traceback_extract_stack.py:23:<module>:
stack = call_function(f)
traceback_example.py :24:call_function():
return call_function(f, recursion_level - 1)
traceback_example.py :24:call_function():
return call_function(f, recursion_level - 1)
traceback_example.py :26:call_function():
return f()
traceback_extract_stack.py:20:f():
return traceback.extract_stack()
Ver también
- Documentación de la biblioteca estándar para traceback
sys
– El módulosys
incluye singletons que contienen la excepción actual.inspect
– El móduloinspect
incluye otras funciones para sondear los marcos en la pila.cgitb
– Otro módulo para formatear muy bien los seguimientos de pila.