La risposta a questa domanda dipende dalla versione di Python che stai utilizzando.
In Python 3
È semplice: le eccezioni sono dotate di un __traceback__attributo che contiene il traceback. Anche questo attributo è scrivibile e può essere comodamente impostato utilizzando il with_tracebackmetodo delle eccezioni:
raise Exception("foo occurred").with_traceback(tracebackobj)
Queste funzionalità sono descritte in minima parte come parte della raisedocumentazione.
Tutto il merito per questa parte della risposta dovrebbe andare a Vyctor, che per primo ha pubblicato queste informazioni . Lo includo qui solo perché questa risposta è bloccata in alto e Python 3 sta diventando più comune.
In Python 2
È fastidiosamente complesso. Il problema con i traceback è che hanno riferimenti a stack frame, e gli stack frame hanno riferimenti ai traceback che hanno riferimenti a stack frame che hanno riferimenti a ... hai capito. Ciò causa problemi per il Garbage Collector. (Grazie a ecatmur per per primo.)
Il modo carino per risolvere questo problema sarebbe interrompere chirurgicamente il ciclo dopo aver lasciato la exceptclausola, che è ciò che fa Python 3. La soluzione di Python 2 è molto più brutta: ti viene fornita una funzione ad-hoc sys.exc_info(), che funziona solo all'interno della except clausola . Restituisce una tupla contenente l'eccezione, il tipo di eccezione e il traceback per qualsiasi eccezione sia attualmente gestita.
Quindi, se sei all'interno della exceptclausola, puoi utilizzare l'output di sys.exc_info()insieme al tracebackmodulo per fare varie cose utili:
>>> 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
Ma come indica la tua modifica, stai cercando di ottenere il traceback che sarebbe stato stampato se la tua eccezione non fosse stata gestita, dopo che è già stata gestita. Questa è una domanda molto più difficile. Sfortunatamente, sys.exc_inforestituisce (None, None, None)quando non viene gestita alcuna eccezione. Anche altri sysattributi correlati non aiutano. sys.exc_tracebackè deprecato e indefinito quando non viene gestita alcuna eccezione; sys.last_tracebacksembra perfetto, ma sembra essere definito solo durante le sessioni interattive.
Se è possibile controllare come l'eccezione è sollevata, si potrebbe essere in grado di utilizzare inspecte di un'eccezione personalizzata per memorizzare alcune delle informazioni. Ma non sono del tutto sicuro di come funzionerebbe.
A dire il vero, catturare e restituire un'eccezione è una cosa insolita da fare. Questo potrebbe essere un segno che devi comunque eseguire il refactoring.