Cómo obtener un seguimiento completo de la pila de excepciones en Python
El siguiente fragmento:
import traceback
def a():
b()
def b():
try:
c()
except:
traceback.print_exc()
def c():
assert False
a()
Produce esta salida:
Traceback (most recent call last):
File "test.py", line 8, in b
c()
File "test.py", line 13, in c
assert False
AssertionError
¿Qué debo usar si quiero el seguimiento completo de la pila incluyendo la llamada a a?
Si importa tengo Python 2.6.6
Editar: Lo que me gustaría obtener es la misma información que obtendría si dejo la excepción de prueba y dejo que la excepción se propague al nivel superior. Este fragmento, por ejemplo:
def a():
b()
def b():
c()
def c():
assert False
a()
Produce esta salida:
Traceback (most recent call last):
File "test.py", line 10, in <module>
a()
File "test.py", line 2, in a
b()
File "test.py", line 5, in b
c()
File "test.py", line 8, in c
assert False
AssertionError
4 answers
No se si hay una mejor manera, pero esto es lo que hice:
import traceback
import sys
def format_exception(e):
exception_list = traceback.format_stack()
exception_list = exception_list[:-2]
exception_list.extend(traceback.format_tb(sys.exc_info()[2]))
exception_list.extend(traceback.format_exception_only(sys.exc_info()[0], sys.exc_info()[1]))
exception_str = "Traceback (most recent call last):\n"
exception_str += "".join(exception_list)
# Removing the last \n
exception_str = exception_str[:-1]
return exception_str
def main1():
main2()
def main2():
try:
main3()
except Exception as e:
print "Printing only the traceback above the current stack frame"
print "".join(traceback.format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2]))
print
print "Printing the full traceback as if we had not caught it here..."
print format_exception(e)
def main3():
raise Exception()
if __name__ == '__main__':
main1()
Y aquí está la salida que obtengo:
Printing only the traceback above the current stack frame
Traceback (most recent call last):
File "exc.py", line 22, in main2
main3()
File "exc.py", line 31, in main3
raise Exception()
Exception
Printing the full traceback as if we had not caught it here...
Traceback (most recent call last):
File "exc.py", line 34, in <module>
main1()
File "exc.py", line 18, in main1
main2()
File "exc.py", line 22, in main2
main3()
File "exc.py", line 31, in main3
raise Exception()
Exception
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-21 23:21:35
Aquí hay una función basada en esta respuesta. También funcionará cuando no haya ninguna excepción:
def full_stack():
import traceback, sys
exc = sys.exc_info()[0]
stack = traceback.extract_stack()[:-1] # last one would be full_stack()
if not exc is None: # i.e. if an exception is present
del stack[-1] # remove call of full_stack, the printed exception
# will contain the caught exception caller instead
trc = 'Traceback (most recent call last):\n'
stackstr = trc + ''.join(traceback.format_list(stack))
if not exc is None:
stackstr += ' ' + traceback.format_exc().lstrip(trc)
return stackstr
print full_stack()
imprimirá el seguimiento completo de la pila hasta la parte superior, incluyendo, por ejemplo, las llamadas de IPython interactiveshell.py
, ya que no hay (que yo sepa) forma de saber quién capturaría las excepciones. Probablemente no valga la pena averiguarlo de todos modos...
Si print full_stack()
se llama desde dentro de un bloque except
, full_stack
incluirá el seguimiento de la pila hasta el raise
. En el intérprete estándar de Python, esto será idéntico al mensaje que recibas cuando no captes la excepción (por lo que del stack[-1]
está ahí, no te importa el bloque except
sino el bloque try
).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:08:59
Use
traceback.print_stack()
Http://docs.python.org/library/traceback.html#traceback.print_stack
suxmac2 $ python out.py File "out.py", line 16, in <module> a() File "out.py", line 5, in a b() File "out.py", line 11, in b traceback.print_stack()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-22 09:16:49
Aquí hay una variante un poco mejor de respuesta de Tobias Kienzler . Funciona igual, pero se puede llamar no directamente en el bloque except
, sino en algún lugar más profundo.
En otras palabras, esta variante imprimirá las mismas pilas, cuando se llame como
try:
...
except Exception:
print full_stack()
O
def print_full_stack():
print full_stack()
try:
...
except Exception:
print_full_stack()
Aquí está el código:
def full_stack():
import traceback, sys
exc = sys.exc_info()[0]
if exc is not None:
f = sys.exc_info()[-1].tb_frame.f_back
stack = traceback.extract_stack(f)
else:
stack = traceback.extract_stack()[:-1] # last one would be full_stack()
trc = 'Traceback (most recent call last):\n'
stackstr = trc + ''.join(traceback.format_list(stack))
if exc is not None:
stackstr += ' ' + traceback.format_exc().lstrip(trc)
return stackstr
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-12 09:14:35