La respuesta a esta pregunta depende de la versión de Python que esté usando.
En Python 3
Es simple: las excepciones vienen equipadas con un __traceback__
atributo que contiene el rastreo. Este atributo también se puede escribir y se puede configurar convenientemente utilizando el with_traceback
método de excepciones:
raise Exception("foo occurred").with_traceback(tracebackobj)
Estas características se describen mínimamente como parte de la raise
documentación.
Todo el crédito por esta parte de la respuesta debe ir a Vyctor, quien primero publicó esta información . Lo incluyo aquí solo porque esta respuesta está atascada en la parte superior y Python 3 se está volviendo más común.
En Python 2
Es fastidiosamente complejo. El problema con los tracebacks es que tienen referencias a marcos de pila, y los marcos de pila tienen referencias a los tracebacks que tienen referencias a marcos de pila que tienen referencias a ... ya se hace una idea. Esto causa problemas al recolector de basura. (Gracias a ecatmur por señalar esto primero).
La buena forma de resolver esto sería romper quirúrgicamente el ciclo después de salir de la except
cláusula, que es lo que hace Python 3. La solución Python 2 es mucho más fea: se le proporciona una función ad-hoc sys.exc_info()
, que solo funciona dentro de la except
cláusula . Devuelve una tupla que contiene la excepción, el tipo de excepción y el rastreo de cualquier excepción que se esté manejando actualmente.
Entonces, si está dentro de la except
cláusula, puede usar la salida de sys.exc_info()
junto con el traceback
módulo para hacer varias cosas útiles:
>>> import sys, traceback
>>> def raise_exception():
... try:
... raise Exception
... except Exception:
... ex_type, ex, tb = sys.exc_info()
... traceback.print_tb(tb)
... finally:
... del tb
...
>>> raise_exception()
File "<stdin>", line 3, in raise_exception
Pero como indica su edición, está intentando obtener el rastreo que se habría impreso si su excepción no se hubiera manejado, después de que ya se haya manejado. Esa es una pregunta mucho más difícil. Desafortunadamente, sys.exc_info
regresa (None, None, None)
cuando no se maneja ninguna excepción. Otros sys
atributos relacionados tampoco ayudan. sys.exc_traceback
está en desuso y no está definido cuando no se maneja ninguna excepción; sys.last_traceback
parece perfecto, pero parece que solo se define durante las sesiones interactivas.
Si puede controlar cómo se genera la excepción, es posible que pueda usar inspect
una excepción personalizada para almacenar parte de la información. Pero no estoy del todo seguro de cómo funcionaría.
A decir verdad, detectar y devolver una excepción es algo inusual. Esto podría ser una señal de que necesita refactorizar de todos modos.