A resposta a esta pergunta depende da versão do Python que você está usando.
Em Python 3
É simples: as exceções vêm equipadas com um __traceback__
atributo que contém o traceback. Este atributo também é gravável e pode ser convenientemente configurado usando o with_traceback
método de exceções:
raise Exception("foo occurred").with_traceback(tracebackobj)
Esses recursos são minimamente descritos como parte da raise
documentação.
Todo o crédito por esta parte da resposta deve ir para Vyctor, que primeiro postou esta informação . Estou incluindo aqui apenas porque essa resposta está presa no topo e o Python 3 está se tornando mais comum.
Em Python 2
É irritantemente complexo. O problema com tracebacks é que eles têm referências a stack frames, e stack frames têm referências a tracebacks que têm referências a stack frames que têm referências a ... você entendeu. Isso causa problemas para o coletor de lixo. (Obrigado a ecatmur por primeiro apontar isso.)
A boa maneira de resolver isso seria quebrar cirurgicamente o ciclo depois de deixar a except
cláusula, que é o que o Python 3 faz. A solução Python 2 é muito mais feia: você recebe uma função ad-hoc sys.exc_info()
, que só funciona dentro da except
cláusula . Ele retorna uma tupla contendo a exceção, o tipo de exceção e o rastreamento para qualquer exceção que esteja sendo tratada no momento.
Portanto, se você estiver dentro da except
cláusula, poderá usar a saída de sys.exc_info()
junto com o traceback
módulo para fazer várias coisas úteis:
>>> 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
Mas, como indica sua edição, você está tentando obter o rastreamento que teria sido impresso se sua exceção não tivesse sido tratada, depois de já ter sido tratada. Essa é uma pergunta muito mais difícil. Infelizmente, sys.exc_info
retorna (None, None, None)
quando nenhuma exceção está sendo tratada. Outros sys
atributos relacionados também não ajudam. sys.exc_traceback
é preterido e indefinido quando nenhuma exceção está sendo tratada; sys.last_traceback
parece perfeito, mas parece ser definido apenas durante as sessões interativas.
Se você puder controlar como a exceção é gerada, você poderá usar inspect
uma exceção personalizada para armazenar algumas das informações. Mas não tenho certeza de como isso funcionaria.
Para dizer a verdade, capturar e retornar uma exceção é algo incomum. Isso pode ser um sinal de que você precisa refatorar de qualquer maneira.