27

私は、サードパーティの開発者がコア アプリケーションの拡張機能を作成するために使用する Python ライブラリに取り組んでいます。

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

アドバイスをよろしくお願いします!

4

7 に答える 7

14

トレースバックの tb_next 要素で上げると、トレースバックの先頭を簡単に削除できます。

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

tb_next は read_only 属性なので、一番下のものを削除する方法がわかりません。プロパティへのアクセスを許可するためにプロパティメカニズムをねじ込むことができるかもしれませんが、その方法はわかりません。

于 2012-12-16T05:50:38.673 に答える
12

ここで jinja2 の機能を見てみましょう。

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

醜いですが、必要なことをしているようです。長いので、ここでは例をコピーして貼り付けません。

于 2009-10-21T22:13:23.860 に答える
2

PEP-3134にも興味があるかもしれません。これは Python 3 で実装されており、上流の例外に 1 つの例外/トレースバックを追加できます。

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

于 2012-09-12T05:24:01.203 に答える
2

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

  1. ライブラリからの例外が開発者のコ​​ードでキャッチされ、代わりに新しい例外が発生した場合、元のトレースバックはもちろん破棄されます。これは、例外が一般的に処理される方法です...元の例外の発生を許可するだけで、それを変更してすべての「上部」フレームを削除すると、トレースバックの最後の行がそうでないため、実際の例外は意味がありませんそれ自体が例外を発生させることができます。
  2. 最後の数フレームを取り除くには、トレースバックを短くするように要求できます... traceback.print_exception() のようなものは、最後のいくつかのエントリをスキップするために使用できる「制限」パラメータを取ります。

そうは言っても、本当に必要な場合は、トレースバックを変更することはかなり可能であるはずです...しかし、どこでそれをしますか? 最上位レベルのラッパー コードの場合は、単にトレースバックを取得し、スライスを取得して不要な部分を削除し、「トレースバック」モジュールの関数を使用して必要に応じてフォーマット/印刷することができます。

于 2009-12-03T21:52:36.730 に答える
0

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

トレースバックを取得し、表示されるべきではない最初のファイルを削除します。次に、Python の動作をシミュレートします。

Traceback (most recent call last):

トレースバックに複数のファイルが含まれている場合にのみ表示されます。これは、余分なフレームがなかったかのように見えます。

ここに私のコード、 string があると仮定します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)
于 2016-09-28T12:27:44.793 に答える