0

ipython などのオープン ソースの python プロジェクトからソース コードを読み取ろうとしています。Eclipse のデバッグ ツールを使用してコードを段階的に実行する場合でも、さまざまなクラスのメソッドの実行フローに従うのが難しいと感じることがよくあります。コードが遠く離れたクラスの特定のメソッドにジャンプする理由はよくわかりません。

継承階層に違いないことはわかっていますが、たどるのが難しいと思います。コードの実行方法を理解するのに役立つツールはありますか? さまざまなメソッドの実行順序を視覚化するのが好きですか? それが完全に素朴な質問ではないことを願っています。

ありがとう。

4

3 に答える 3

0

MIT の Web サイトには、実行を追跡して画像で表示するプログラムがあります

于 2012-05-30T02:29:21.320 に答える
0

私はあなたと同じ船に乗っていました。結局、私は自分のものを作成しました。つまり、これに使用できる組み込みの方法がたくさんありますが、少し手間がかかります。そのような方法の 1 つは、トレーサー(実行中のコードのある種のアナライザー) を設定することです。

ソース:

import sys, inspect

class Tracer(object):

    def __init__(self):
        self.tracing_packages = []
        self.whitespace = '    '
        self.indent_lvl = 0

    def trace(self, frame, event, arg):
        # Module info
        mod = inspect.getmodule(frame)
        if mod:
            modpath = mod.__name__
        else:
            modpath = '<no module>'
        # Just return if not interested in package
        for to_trace in self.tracing_packages:
            if not modpath.startswith(to_trace):
                return self.trace
        # Other info
        fn_name = frame.f_code.co_name
        src_lines = inspect.getsource(frame).split('\n')
        src_line_start = src_lines[0]
        src_line_end = src_lines[-1]
        lineno = frame.f_lineno
        ws = self.whitespace
        # Printing
        if event == 'call':
            self.indent_lvl += 1
            print('%scallin: %s %s %s' % (self.indent_lvl*ws, modpath, fn_name, str(arg)))
        elif event == 'return':
            if isinstance(arg, object):
                ret = type(arg)
            else:
                ret = str(arg)
            print('%sreturn: %s' % (self.indent_lvl*ws, ret))
            self.indent_lvl -= 1
        return self.trace

    def watch_package(self, packname):
        self.tracing_packages.append(packname)

使用法

あなたの場合、次のように入力するだけです:

tracer = Tracer()
tracer.watch_package('IPython')
sys.settrace(tracer.trace)

次に、関数を実行しようとすると、呼び出されている同じパッケージの他の関数を含む呼び出しチェーン全体が出力されます。

その他の例

特定の機能の流れやパッケージ全体の流れを知りたいときに使います。パッケージ全体の俯瞰図が必要な場合は、pylintの pyreverse を使用して UML ダイアグラムを作成することもできます。

とにかく、PyOCDパッケージをトレースする例を次に示します。

>>> import sys, inspect, pyOCD
>>> tracer = Tracer()
>>> tracer.watch_package('pyOCD')
>>> sys.settrace(tracer.trace)
>>> pyOCD.board.MbedBoard.listConnectedBoards()
    callin: pyOCD.board.mbed_board listConnectedBoards None
        callin: pyOCD.board.mbed_board getAllConnectedBoards None
            callin: pyOCD.interface.pyusb_backend getAllConnectedInterface
                callin: pyOCD.interface.pyusb_backend __init__ None
                    callin: pyOCD.interface.interface __init__ None
                    return: <type 'NoneType'>
                return: <type 'NoneType'>
                callin: pyOCD.interface.pyusb_backend start_rx None
                return: <type 'NoneType'>
            return: <type 'list'>

            ...
于 2015-05-14T17:03:23.137 に答える
0

ジャンプは、関数が別の関数を呼び出し、その関数が別の関数を呼び出すことによって発生します。

于 2012-05-30T02:25:59.007 に答える