0

我正在尝试从一些开源 python 项目中读取一些源代码,比如 ipython。我经常发现很难跟踪不同类中方法的执行流程,即使使用 eclipse 的调试工具并逐步执行代码。我不太清楚为什么代码会跳转到远相关类中的某些方法。

我知道它必须是继承层次结构,但我发现很难遵循。是否有任何工具可以帮助理解代码的执行方式?喜欢可视化不同方法的执行顺序?希望这不是一个完全幼稚的问题。

谢谢。

4

3 回答 3

0

跳转是由您的函数调用另一个函数引起的,该函数在 tern 调用另一个函数。

于 2012-05-30T02:25:59.007 回答
0

麻省理工学院网站有一个程序可以跟踪执行并以图片显示它们,您可能会发现它很有用:http: //people.csail.mit.edu/pgbovine/python/tutor.html#mode=edit

于 2012-05-30T02:29:21.320 回答
0

我和你在同一条船上。最后我创造了自己的东西。也就是说,您可以使用许多内置方法,但这需要一些努力。一种这样的方法是设置跟踪器——在代码执行时对代码进行某种分析器。

资源:

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 回答