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_traceback
metodo delle eccezioni:
raise Exception("foo occurred").with_traceback(tracebackobj)
Queste funzionalità sono descritte in minima parte come parte della raise
documentazione.
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 except
clausola, 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 except
clausola, puoi utilizzare l'output di sys.exc_info()
insieme al traceback
modulo 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_info
restituisce (None, None, None)
quando non viene gestita alcuna eccezione. Anche altri sys
attributi correlati non aiutano. sys.exc_traceback
è deprecato e indefinito quando non viene gestita alcuna eccezione; sys.last_traceback
sembra perfetto, ma sembra essere definito solo durante le sessioni interattive.
Se è possibile controllare come l'eccezione è sollevata, si potrebbe essere in grado di utilizzare inspect
e 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.