この質問に対する答えは、使用しているPythonのバージョンによって異なります。
Python3の場合
簡単です。例外に__traceback__
は、トレースバックを含む属性が備わっています。この属性も書き込み可能でありwith_traceback
、例外の方法を使用して便利に設定できます。
raise Exception("foo occurred").with_traceback(tracebackobj)
これらの機能は、raise
ドキュメントの一部として最小限に説明されています。
回答のこの部分のすべてのクレジットは、この情報を最初に投稿したVyctorに送られる必要があります。この答えが一番上に留まっていて、Python 3がより一般的になっているという理由だけで、ここに含めています。
Python2の場合
それは厄介なほど複雑です。トレースバックの問題は、スタックフレームへの参照があり、スタックフレームには、への参照があるスタックフレームへの参照があるトレースバックへの参照があることです。これにより、ガベージコレクターに問題が発生します。(これを最初に指摘してくれたecatmurに感謝します。)
これを解決する良い方法は、Python 3が行うことである、句を離れた後に外科的にサイクルを中断することです。except
Python 2ソリューションははるかに醜いです。アドホック関数が提供されます。この関数は、句sys.exc_info()
内でのみ 機能します。例外、例外タイプ、および現在処理されている例外のトレースバックを含むタプルを返します。except
したがって、except
句の中にいる場合は、モジュールsys.exc_info()
とともにの出力を使用して、さまざまな便利なことを行うことができます。traceback
>>> 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
ただし、編集で示されているように、例外が処理された後、例外が処理されなかった場合に出力されたであろうトレースバックを取得しようとしています。それはもっと難しい質問です。残念ながら、例外が処理されていないときに戻ります。他の関連する属性も役に立ちません。例外が処理されていない場合は非推奨で未定義です。完璧に見えますが、インタラクティブセッション中にのみ定義されているように見えます。sys.exc_info
(None, None, None)
sys
sys.exc_traceback
sys.last_traceback
inspect
例外の発生方法を制御できる場合は、カスタム例外を使用して一部の情報を格納できる可能性があります。しかし、それがどのように機能するかは完全にはわかりません。
実を言うと、例外をキャッチして返すことは、一種の珍しいことです。これは、とにかくリファクタリングする必要がある兆候かもしれません。