2

Python では compile() 文字列を exec() でより高速に実行できます。しかし、使用するとすぐに、exec で例外が発生したときに情報が失われました。

たとえば、不明なメソッドを呼び出すコード スニペットを次に示します (デモ用)。

code = 'my_unknown_method()'
bytecode = compile(code, '<string>', 'exec')

その後、そのバイトコードで exec を呼び出しています。

exec bytecode

表示されたトレースバックは次のとおりです。

Traceback (most recent call last):
  File "test.py", line 3, in <module>
    exec bytecode
  File "<string>", line 1, in <module>
NameError: name 'my_unknown_method' is not defined   

「exec()」フレームがわかりにくくなりました。次のようなより良い例外が必要です。

Traceback (most recent call last):
  File "test.py", line 3, in <module>
    exec "my_unknown_method()"
  File "<string>", line 1, in <module>
NameError: name 'my_unknown_method' is not defined   

何かご意見は ?

ノート:

  • compile の 2 番目の引数 (ファイル名) を使用したくない
  • フレームの f_code を調べて変更することをテストしましたが、読み取り専用属性です。

編集: sys.excepthook をさらに調べた後、python ソース コード/traceback.c で、python が行の内容を表示したい場合、ファイルが見つかった場合は直接 fopen() であることがわかりました。独自のコンテンツを表示するためのフックはまったくありません。唯一の方法は、ディスク上に実際の偽のファイル名を作成することですか? 誰 ?

EDIT2: いくつかの jinja2 デバッグ コードをチェックしましたが、トレースバックも書き直していますが、内容は書き直していません。カスタム以外のフックが必要ですか? それに関する私の懸念は、それがトレースバック自体にないためです。ユーザー/モジュール/何かが例外を受け取った場合、トレースバックには貴重な情報が含まれません。

4

3 に答える 3

4

Armin Ronacher によるこの講演をご覧ください。彼は Jinja2 の作成者であり、この講演では、Jinja2 でスタック トレースを操作する方法について説明しました。私の記憶が正しければ、彼は ctypes を使用して Python の C レベルでデータ構造を操作していました。ちなみに、私の意見では、この講演は Europython 2011 全体で最高の講演でした。

于 2011-11-25T22:52:38.563 に答える
2

詳細な検索の後、それは不可能です.CPythonは独自のAPIを使用してファイルの場所などを特定しており、純粋なPythonでパッチを適用することはできません.

于 2012-02-08T12:24:38.150 に答える
0

このようなものはどうですか:

import sys
def mkexec(code_str):
    bc = compile(code, '<string>', 'exec')
    def run():
        try:
            exec bc
        except: # Yes I know a bare except
            t, v, tb = sys.exc_info()
            raise MyUsefullException("%s raised %s" % (code_str, v))
    return run

exe = mkexec("some_unknown_something()")
exe()
于 2011-11-18T11:36:56.070 に答える