python插装--sys.settrace

简单来说最近在做回归测试的相关工作→

回归测试需要根据版本之间代码的变更选择测试用例→

尝试静态和动态生成调用图方法后选择用动态生成方法解决→

选用第三方库pycallgraph魔改了一部分算是满足了跑实验的需求→

跑的差不多了想搞清楚内部具体怎么实现插装→

有了本文

看过部分源码后发现使用了sys.settrace进行插桩跟踪运行时的轨迹,不知怎么发现SO上的这个问题,

python插装--sys.settrace_第1张图片

项目开发者在13年就实现这玩意儿了,虽然这个项目在15年就已经没继续更新,但是依然能比较好的兼容最新的python版本(大概是用到的built-in lib没啥大变化)。

跟踪函数需要接收三个参数frame( https://docs.python.org/3/library/sys.html#sys.settrace ),event( https://docs.python.org/3/reference/datamodel.html#types ),arg( https://docs.python.org/3/library/sys.html#sys.settrace )。其中arg的值与event类型有关。

通过内省inspect可获得代码的模块信息,包括模块路径和模块名,跟踪前设置sys.settrace(tracer)进行跟踪,sys.settrace(None)关闭跟踪,frame.f_locals可以获取调用函数时参数的信息,具体更多属性可以在frame后的链接中查找。

import sys
from main import add
import inspect


class Tracer:

    def dump(self, frame, event, arg):
        code = frame.f_code
        module = inspect.getmodule(code)
        module_name = ""
        module_path = ""
        if module:
            module_path = module.__file__
            module_name = module.__name__
        print(event, module_path, module_name, code.co_name, frame.f_lineno, frame.f_locals, arg)

    def trace(self, frame, event, arg):
        self.dump(frame, event, arg)
        return self.trace

    def collect(self, func, *args, **kwargs):
        sys.settrace(self.trace)
        func(*args, **kwargs)
        sys.settrace(None)


if __name__ == "__main__":
    t = Tracer()
    t.collect(add, 1, 2)

然后给了一个demo,让我们写的tracer跟踪它的执行。

def add(a, b):
    c = 3
    d = 4
    e = c + d
    return a + b + e


if __name__ == "__main__":
    print(add(1, 2))

运行结果:

python插装--sys.settrace_第2张图片

完。

你可能感兴趣的:(工具)