Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Instrumenting Python Code

I want to instrument every if condition encountered inside a python function automatically. For example if my code hits:

if x > 2:
    #do something

I want to record/ print "x > 2" to the console.

I found this tool "equip" https://github.com/neuroo/equip/ but it only instuments at function boundaries. I think I need to be able to instrument at the bytecode instruction level to get those conditionals out.

Currently, I have to manually stdout/append after every if condition like

if x > 2:    
    list.append("x>2")
like image 364
Zain Qasmi Avatar asked Nov 28 '17 17:11

Zain Qasmi


Video Answer


1 Answers

This is a simple example to get you started. Suppose you have a module like this:

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


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

If you exec foo, you get:

small
big

Now you want to print the test clause of every if statement if the test is True. Lets start by importing foo:

>>> import foo

Then get the source code:

>>> source = inspect.getsource(foo)

Lets parse the source in order to get an abstract syntax tree:

>>> tree = ast.parse(source)

The next step is defining a NodeTransformer that will modify the tree:

>>> 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)

In order to modify the tree we make our IfTransformer visit all nodes:

>>> IfTransformer().visit(tree)

Then you can compile and execute your new source:

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

small
(x > 100)

big

For each if clause where the test is True, you got the test printed. A smart guy like you can figure everything out from here.

Check out this video from Pycon 2011.

like image 71
Paulo Scardine Avatar answered Sep 19 '22 05:09

Paulo Scardine