web-dev-qa-db-ja.com

traceback / sys.exc_info()値を変数に保存する方法は?

エラーの名前とトレースバックの詳細を変数に保存します。これが私の試みです。

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]オブジェクトの使用方法を知りたいです。

104
codersofthedark

これは私がそれを行う方法です:

>>> 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'

ただし、後で変数を処理する方法に応じて、より適切なメソッドが見つかる可能性があるため、 トレースバックドキュメント を確認する必要があります。

150
mac

sys.exc_info()は、3つの値(タイプ、値、トレースバック)を持つタプルを返します。

  1. ここでtypeは、処理される例外の例外タイプを取得します
  2. 値は、例外クラスのコンストラクターに渡される引数です
  3. トレースバックには、例外が発生した場所などのスタック情報が含まれます。

たとえば、次のプログラムで

try:

    a = 1/0

except Exception,e:

    exc_Tuple = sys.exc_info()

タプルを印刷すると、値はこれになります。

  1. exc_Tuple [0]値は "ZeroDivisionError"
  2. exc_Tuple [1]の値は、「整数除算またはゼロによるモジュロ」(例外クラスにパラメーターとして渡される文字列)
  3. exc_Tuple [2]の値は「(一部のメモリアドレス)のトラックバックオブジェクト

上記の詳細は、単に例外を文字列形式で出力することでも取得できます。

print str(e)
22
keya

モジュールおよび関数の名前と行番号に簡単にアクセスしたい場合は、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'
16
Nathan

例外ハンドラーから例外オブジェクトまたはトレースバックオブジェクトを取り出すときは注意してください。これにより循環参照が発生し、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()は、ノートブックが終了するか、別の例外が以前に保存されたバックトレースを上書きするまで解放されません。これは非常に問題です。フレームのクリーニングなしでトレースバックを保存しないでください。提出済みの修正 ここ

1
stason

オブジェクトは、Exception.with_traceback()関数のパラメーターとして使用できます。

except Exception as e:
    tb = sys.exc_info()
    print(e.with_traceback(tb[2]))
0
Hansen D'Silva