如何在python程序中注入代码,以便它们可以在if语句中打印条件?

时间:2017-11-19 18:55:32

标签: python python-2.7 instrumentation

我正在寻找一种方法(内部注入代码)python程序。 例如,如果程序遇到if条件x > 2,我想在print条件后自动添加if语句,该条件会打印到控制台x > 2

该程序的源代码不可用。

1 个答案:

答案 0 :(得分:3)

您可以使用ast模块,但仍需要源代码。如果您只有字节码,则必须使用类似uncompyle6的内容才能获取源代码 - 因为您自动执行此操作,如果源代码被混淆无关紧要。

假设你有一个这样的模块:

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