それ以来、回避策を見つけましたが、それでも答えを知りたいです。
3 に答える
トレースバックは、現在のスレッドで呼び出された各関数/メソッドのスタックフレームへの参照を、最上部のフレームからエラーが発生したポイントまで保持します。各スタックフレームは、スタック内の各関数が呼び出されたときに有効だったローカル変数とグローバル変数への参照も保持します。
pickleが何をシリアル化し、何を無視するかを知る方法がないため、トレースバックをpickle化できた場合、アプリケーション状態全体の移動スナップショットをpickle化することになります。pickleが実行されると、他のスレッドが共有変数の値。
1つの解決策は、トレースバックをウォークバックし、保存する必要のある情報のみを抽出するための選択可能なオブジェクトを作成することです。
あなたはtblibを使うことができます
try:
1 / 0
except Exception as e:
raise Exception("foo") from e
except Exception as e:
s = pickle.dumps(e)
raise pickle.loads(s)
完全な呼び出しコンテキスト(トレースバック+グローバル+各フレームのローカル)を保存することに関心があると思います。
これは、2つの異なる呼び出しコンテキストでの同じ関数の動作の違いを判断したり、それらのトレースバックを処理、表示、または比較するための独自の高度なツールを構築したりする場合に非常に役立ちます。
問題は、picklが、ローカルまたはグローバルに存在する可能性のあるすべてのタイプのオブジェクトをシリアル化する方法を知らないことです。
独自のオブジェクトを作成して保存し、 picklabeではないすべてのオブジェクトを除外できると思います。このコードは基礎として役立ちます:
import sys, traceback
def print_exc_plus():
"""
Print the usual traceback information, followed by a listing of all the
local variables in each frame.
"""
tb = sys.exc_info()[2]
while 1:
if not tb.tb_next:
break
tb = tb.tb_next
stack = []
f = tb.tb_frame
while f:
stack.append(f)
f = f.f_back
stack.reverse()
traceback.print_exc()
print "Locals by frame, innermost last"
for frame in stack:
print
print "Frame %s in %s at line %s" % (frame.f_code.co_name,
frame.f_code.co_filename,
frame.f_lineno)
for key, value in frame.f_locals.items():
print "\t%20s = " % key,
#We have to be careful not to cause a new error in our error
#printer! Calling str() on an unknown object could cause an
#error we don't want.
try:
print value
except:
print "<ERROR WHILE PRINTING VALUE>"
ただし、オブジェクトを印刷する代わりに、独自の選択可能な表現を使用してリストに追加できます(jsonまたはyml形式の方が良い場合があります)。
関数を生成する複雑なワークフローを実行せずに、関数に対して同じ状況を再現するために、このすべての呼び出しコンテキストをロードしたい場合があります。これが(メモリ参照のために)実行できるかどうかはわかりませんが、その場合は、フォーマットから逆シリアル化する必要があります。