エラーの名前とトレースバックの詳細を変数に保存します。これが私の試みです。
import sys
try:
try:
print x
except Exception, ex:
raise NameError
except Exception, er:
print "0", sys.exc_info()[0]
print "1", sys.exc_info()[1]
print "2", sys.exc_info()[2]
出力:
0 <type 'exceptions.NameError'>
1
2 <traceback object at 0xbd5fc8>
望ましい出力:
0 NameError
1
2 Traceback (most recent call last):
File "exception.py", line 6, in <module>
raise NameError
追伸これはトレースバックモジュールを使用して簡単に実行できることは知っていますが、ここでsys.exc_info()[2]オブジェクトの使用方法を知りたいです。
これは私がそれを行う方法です:
>>> import traceback
>>> try:
... int('k')
... except:
... var = traceback.format_exc()
...
>>> print var
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ValueError: invalid literal for int() with base 10: 'k'
ただし、後で変数を処理する方法に応じて、より適切なメソッドが見つかる可能性があるため、 トレースバックドキュメント を確認する必要があります。
sys.exc_info()は、3つの値(タイプ、値、トレースバック)を持つタプルを返します。
たとえば、次のプログラムで
try:
a = 1/0
except Exception,e:
exc_Tuple = sys.exc_info()
タプルを印刷すると、値はこれになります。
上記の詳細は、単に例外を文字列形式で出力することでも取得できます。
print str(e)
モジュールおよび関数の名前と行番号に簡単にアクセスしたい場合は、traceback.extract_stack()
を使用します。
''.join(traceback.format_stack())
出力のように見える文字列だけが必要な場合は、traceback.print_stack()
を使用します。
''.join()
の要素には\n
が含まれているため、format_stack()
を使用しても複数行の文字列を取得することに注意してください。以下の出力を参照してください。
import traceback
を忘れないでください。
traceback.extract_stack()
からの出力は次のとおりです。読みやすくするためにフォーマットが追加されました。
>>> traceback.extract_stack()
[
('<string>', 1, '<module>', None),
('C:\\Python\\lib\\idlelib\\run.py', 126, 'main', 'ret = method(*args, **kwargs)'),
('C:\\Python\\lib\\idlelib\\run.py', 353, 'runcode', 'exec(code, self.locals)'),
('<pyshell#1>', 1, '<module>', None)
]
''.join(traceback.format_stack())
からの出力は次のとおりです。読みやすくするためにフォーマットが追加されました。
>>> ''.join(traceback.format_stack())
' File "<string>", line 1, in <module>\n
File "C:\\Python\\lib\\idlelib\\run.py", line 126, in main\n
ret = method(*args, **kwargs)\n
File "C:\\Python\\lib\\idlelib\\run.py", line 353, in runcode\n
exec(code, self.locals)\n File "<pyshell#2>", line 1, in <module>\n'
例外ハンドラーから例外オブジェクトまたはトレースバックオブジェクトを取り出すときは注意してください。これにより循環参照が発生し、gc.collect()
が収集できなくなります。これは、適切なタイミングでトレースバックオブジェクトがクリアされず、finally
セクションのgc.collect()
セクションへの明示的な呼び出しでも何も実行されないipython/jupyterノートブック環境で特に問題があるようです。そして、そのためにメモリが回収されないいくつかの巨大なオブジェクトがある場合、それは大きな問題です(例えば、CUDAのメモリ不足の例外は、このソリューションなしでは回復するために完全なカーネルの再起動が必要です)。
一般に、トレースバックオブジェクトを保存する場合は、次のようにlocals()
への参照からオブジェクトをクリアする必要があります。
import sys, traceback, gc
type, val, tb = None, None, None
try:
myfunc()
except:
type, val, tb = sys.exc_info()
traceback.clear_frames(tb)
# some cleanup code
gc.collect()
# and then use the tb:
if tb:
raise type(val).with_traceback(tb)
Jupyter Notebookの場合、少なくとも例外ハンドラー内でそれを行う必要があります。
try:
myfunc()
except:
type, val, tb = sys.exc_info()
traceback.clear_frames(tb)
raise type(val).with_traceback(tb)
finally:
# cleanup code in here
gc.collect()
python 3.7でテスト済み。
追伸ipythonまたはjupyterノートブックenvの問題は、トレースバックを保存し、後でいつでも利用できるようにする%tb
マジックがあることです。その結果、トレースバックに参加しているすべてのフレームのlocals()
は、ノートブックが終了するか、別の例外が以前に保存されたバックトレースを上書きするまで解放されません。これは非常に問題です。フレームのクリーニングなしでトレースバックを保存しないでください。提出済みの修正 ここ 。
オブジェクトは、Exception.with_traceback()
関数のパラメーターとして使用できます。
except Exception as e:
tb = sys.exc_info()
print(e.with_traceback(tb[2]))