2

Pythonコードをトレースし、ローカル変数値への変更のレポートを出力するプログラムを作成しようとしています。単純な割り当て、ループ、および関数呼び出しでうまく機能していますが、importステートメントを使用すると問題が発生します。

メインモジュールのコードのみをトレースしたいのですが、インポートされたモジュールが呼び出されたらすぐにトレースを停止したいと思います。これは、作成した単純なモジュールをインポートするときに実行できます。フレームのコードオブジェクトが別のファイルを指している場合は、トレースを停止します。

ただし、decimalモジュールをインポートしようとすると、これは機能しません。モジュールで実行されているコードのほとんどを削除できますが、メインモジュールで実行されていると主張するdecimalコードブロックへの呼び出しが1つあります。DecimalTupleただし、そのモジュールには行番号が存在しないため、これは意味がありません。

フレームまたはコードオブジェクトDecimalTupleに、メインモジュールにないことを伝えるために使用できる他の属性はありますか?もちろん、の特殊なケースを追加することもできDecimalTupleますが、他のモジュールで同じ問題が発生した場合は役に立ちません。

これが私の例です。引用符で囲まれたコードを実行し、。を使用して呼び出しをトレースしますsettrace()。コメントアウトすると、最初の2行global_trace()に、他のモジュールで実行されるすべてのコードも表示されます。

import sys

class tracer:

    count = 0

    def __init__(self):
        self.index = tracer.count = tracer.count + 1

    def global_trace(self, frame, event, arg):
        if frame.f_code.co_filename != '<string>':
            return
        print 'global %d, line %d: %s, %s' % (self.index,
                                         frame.f_lineno,
                                         event,
                                         frame.f_code)
        return tracer().local_trace

    def local_trace(self, frame, event, arg):
        print 'local %d, line %d: %s, %s' % (self.index,
                                         frame.f_lineno,
                                         event,
                                         frame.f_code)
        return self.local_trace

code = """\
def foo(r):
    return r + 3

y = foo(2)

import decimal

x = decimal.Decimal('10')
"""

sys.settrace(tracer().global_trace)

exec code in dict()

これがトレース出力です。の呼び出しfoo()とその実行はすべて<string>、メインモジュールとして渡したコードの文字列を表すモジュール内にあることがわかります。ただし、6行目のimportステートメントに到達すると、モジュールに含まれていない可能性のあるコードの呼び出しを開始し<string>ます。

global 1, line 1: call, <code object <module> at 0x266a030, file "<string>", line 1>
local 2, line 1: line, <code object <module> at 0x266a030, file "<string>", line 1>
local 2, line 4: line, <code object <module> at 0x266a030, file "<string>", line 1>
global 1, line 1: call, <code object foo at 0x266a730, file "<string>", line 1>
local 3, line 2: line, <code object foo at 0x266a730, file "<string>", line 1>
local 3, line 2: return, <code object foo at 0x266a730, file "<string>", line 1>
local 2, line 6: line, <code object <module> at 0x266a030, file "<string>", line 1>
global 1, line 1: call, <code object <module> at 0x27c2130, file "<string>", line 1>
local 4, line 1: line, <code object <module> at 0x27c2130, file "<string>", line 1>
global 1, line 1: call, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 1: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 2: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 4: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 6: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 8: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 12: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 13: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 20: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 24: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 28: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 30: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 37: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 41: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 42: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 43: line, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 5, line 43: return, <code object DecimalTuple at 0x27c21b0, file "<string>", line 1>
local 4, line 1: return, <code object <module> at 0x27c2130, file "<string>", line 1>
local 2, line 8: line, <code object <module> at 0x266a030, file "<string>", line 1>
local 2, line 8: return, <code object <module> at 0x266a030, file "<string>", line 1>
4

1 に答える 1

2

結局のところ、これが発生するのは、collections.namedtupleいくつかの非常に厄介なことを行うためです (そしてDecimalTupleは であるnamedtupleため、 への呼び出しはimport decimal後でこのコードを呼び出します)。たまたま、300 行目あたりcollections.py(少なくとも Python 2.7 では、バージョンによって行番号が異なる場合があります) に、次のようなコメントが表示されます。

# Execute the template string in a temporary namespace and
# support tracing utilities by setting a value for frame.f_globals['__name__']

この後のコードにより、トレーサーは観察しているものを誤って解釈します。クラスを作成するテンプレートはexecそれ自体を使用して行われるため、<string>「ファイル」で実行されるコードが増えます <string>

于 2012-05-27T06:49:11.903 に答える