2009-10-21 11 views
15

私は、コアアプリケーションの拡張機能を書くためにサードパーティの開発者が使用するPythonライブラリに取り組んでいます。例外発生時にPythonトレースバックオブジェクトを変更するにはどうすればよいですか?

例外を発生させるときにトレースバックを変更できるかどうかを知りたいので、最後のスタックフレームは例外を発生させたライブラリのラインではなく、開発者のコ​​ードのライブラリ関数への呼び出しです。また、スタックの最下部には、コードを最初にロードするときに使用する関数への参照が含まれているフレームもいくつかあります。

アドバイスを事前にいただきありがとうございます!

答えて

1

トレースバックを変更しないのはどうですか?あなたが要求する2つのものは、どちらももっと簡単に別の方法で実行できます。

  1. ライブラリからの例外が開発者のコ​​ードで検出され、代わりに新しい例外が発生した場合は、元のトレースバックが当然投げられます。これは例外が一般的にどのように処理されるかです。元の例外を発生させるだけで、すべての "上位"フレームを削除すると、実際の例外は意味を持ちません。なぜなら、トレースバックの最後の行はそれ自体は例外を発生させることができます。
  2. 最後の数フレームを取り除くには、トレースバックを短くするように要求することができます。traceback.print_exception()のようなものは、最後のいくつかのエントリをスキップするために使用できる "limit"パラメータをとります。

本当に必要な場合は、トレースバックを作成するのはかなり可能なはずですが、どこでやるのですか?最上位レベルのラッパーコードでは、単にトレースバックを取得し、不要な部分を削除するためにスライスを取ってから、「トレースバック」モジュールの関数を使用して必要に応じて書式設定/印刷することができます。

+7

私はdownvoted、ここに理由があります:この回答は良いアドバイスを提供しますが、それは実際に質問に答えるものではありません。 –

+3

@BryanOakley:アドバイスが非常に関連していて、コメントに収まるには大きすぎる場合、それは答えに属します。どちらかというと、知識をSOから遠ざけておくことは非常に悲しいことです。だから、私はこれらのケースでダウンボートが適切だとは思わない。 – max

+2

@max:あなたが正しいと思います。私は自分自身もこのような質問に答えています - 「あなたはそれをすることができますが、なぜここに考えるべきか」責任を持ってくれてありがとう。私ができるなら私は私の投票を変更するだろう。 –

7

はここに何をするかJinja2のを見てみましょう:

https://github.com/mitsuhiko/jinja2/blob/5b498453b5898257b2287f14ef6c363799f1405a/jinja2/debug.py

それは醜いですが、あなたが完了必要なものをやっているようです。私はこの例をここにコピー&ペーストすることはしません。

+0

は私がこれを書く時には、上記のリンクは、404エラーが発生します。 –

+1

キーのように見えます。 –

1

PEP-3134はpython 3で実装されていて、1つの例外/トレースバックを上流の例外に組み込むことができます。

これはトレースバックを変更するのと全く同じことではありませんが、「短いバージョン」をライブラリユーザーに伝えて「長いバージョン」を利用できる理想的な方法でしょう。

11

あなたはトレースバックのtb_next要素を上昇させることにより、簡単にトレースバックの上部を削除することができます。

except: 
    ei = sys.exc_info() 
    raise ei[0], ei[1], ei[2].tb_next 

tb_nextがREAD_ONLY属性であるので、私はからのものを削除する方法を知りません。ボトム。あなたはプロパティへのアクセスを許可するためにプロパティのメカニズムに悩むことができるかもしれませんが、それを行う方法はわかりません。

+2

これをpython 3でどのように管理するか考えてみましょうか?私はこれを自分で動作させることはできません。 –

0

このコードはあなたにとって興味深いかもしれません。

トレースバックを実行し、最初に表示されないファイルを削除します。そして、それは、Pythonの挙動をシミュレート:トレースバックに複数のファイルが含まれている場合

Traceback (most recent call last): 

にのみ表示されます。 これはちょうど私の余分なフレームがそこになかったかのように見えます。

ここに私のコードは、文字列textがあると仮定:

try: 
    exec(text) 
except: 
    # we want to format the exception as if no frame was on top. 
    exp, val, tb = sys.exc_info() 
    listing = traceback.format_exception(exp, val, tb) 
    # remove the entry for the first frame 
    del listing[1] 
    files = [line for line in listing if line.startswith(" File")] 
    if len(files) == 1: 
     # only one file, remove the header. 
     del listing[0] 
    print("".join(listing), file=sys.stderr) 
    sys.exit(1) 
関連する問題