检测Python代码

时间:2017-11-28 17:28:19

标签: python instrumentation

我想自动检测python函数中遇到的每个if条件。例如,如果我的代码命中:

if x > 2:
    #do something

我想将“x> 2”录制/打印到控制台。

我发现这个工具“装备”https://github.com/neuroo/equip/ 但它只是在功能边界的实验。我想我需要能够在字节码指令级进行检测以获得这些条件。

目前,我必须在每个if条件之后手动stdout / append,如

if x > 2:    
    list.append("x>2")

1 个答案:

答案 0 :(得分:6)

这是一个简单的例子,可以帮助您入门。假设你有一个这样的模块:

def foo(x):
    if x > 100:
        print('big')
    else:
        print('small')


if __name__ == '__main__':
    foo(5)
    foo(500)

如果你执行foo,你会得到:

small
big

现在,如果测试为if,则要打印每个True语句的test子句。让我们先导入foo:

>>> import foo

然后获取源代码:

>>> source = inspect.getsource(foo)

让我们解析源代码以获得抽象语法树:

>>> tree = ast.parse(source)

下一步是定义一个将修改树的NodeTransformer:

>>> class IfTransformer(ast.NodeTransformer):
         def visit_If(self, node):
             new_node = ast.Expr(value=ast.Call(
                  func=ast.Name(id='print', ctx=ast.Load()), 
                  args=[ast.Str(s=astunparse.unparse(node.test))], 
                  keywords=[]
             ))
             node.body.insert(0, new_node)
             return ast.fix_missing_locations(node)

为了修改树,我们让IfTransformer访问所有节点:

>>> IfTransformer().visit(tree)

然后你可以编译并执行你的新资源:

>>> exec(compile(tree, 'foo.py', 'exec'))
(__name__ == '__main__')

small
(x > 100)

big

对于测试为True的每个if子句,您打印了测试。像你这样聪明的人可以从这里找出所有的东西。

查看this video from Pycon 2011