La réponse à cette question dépend de la version de Python que vous utilisez.
Dans Python 3
C'est simple: les exceptions sont équipées d'un __traceback__attribut qui contient le traçage. Cet attribut est également accessible en écriture et peut être facilement défini à l'aide de la with_tracebackméthode des exceptions:
raise Exception("foo occurred").with_traceback(tracebackobj)
Ces fonctionnalités sont décrites de manière minimale dans le cadre de la raisedocumentation.
Tout le mérite de cette partie de la réponse doit revenir à Vyctor, qui a publié cette information en premier . Je l'inclus ici uniquement parce que cette réponse est bloquée en haut et que Python 3 est de plus en plus courant.
Dans Python 2
C'est extrêmement complexe. Le problème avec les retraits est qu'ils ont des références aux cadres de pile, et les cadres de pile ont des références aux retraçages qui ont des références aux cadres de pile qui ont des références à ... vous voyez l'idée. Cela provoque des problèmes pour le garbage collector. (Merci à ecatmur d' avoir d'abord signalé cela.)
La bonne façon de résoudre ce problème serait de rompre chirurgicalement le cycle après avoir quitté la exceptclause, ce que fait Python 3. La solution Python 2 est beaucoup plus moche: vous disposez d'une fonction ad-hoc sys.exc_info(), qui ne fonctionne qu'à l'intérieur de la except clause . Il retourne un tuple contenant l'exception, le type d'exception et la trace de toute exception actuellement gérée.
Donc, si vous êtes à l'intérieur de la exceptclause, vous pouvez utiliser la sortie de sys.exc_info()avec le tracebackmodule pour faire diverses choses utiles:
>>> 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
Mais comme votre modification l'indique, vous essayez d'obtenir le traçage qui aurait été imprimé si votre exception n'avait pas été gérée, après l'avoir déjà gérée. C'est une question beaucoup plus difficile. Malheureusement, sys.exc_inforetourne (None, None, None)lorsqu'aucune exception n'est gérée. D'autres sysattributs connexes n'aident pas non plus. sys.exc_tracebackest obsolète et indéfinie lorsqu'aucune exception n'est gérée; sys.last_tracebacksemble parfait, mais il ne semble être défini que lors de sessions interactives.
Si vous pouvez contrôler la manière dont l'exception est déclenchée, vous pourrez peut-être utiliser inspectune exception personnalisée pour stocker certaines des informations. Mais je ne suis pas tout à fait sûr de savoir comment cela fonctionnerait.
Pour dire la vérité, attraper et renvoyer une exception est quelque chose d'inhabituel à faire. Cela pourrait être un signe que vous devez de toute façon refactoriser.