问题
I am looking for a way to instrument (Inject code inside) python programs.
For example, if a program hits the if
condition x > 2
, I want to automatically add a print
statement following the if
condition which prints to the console x > 2
.
The source code of the program is not available.
回答1:
You can use the ast
module, but you still need the sources. If you have only the bytecode, you must use something like uncompyle6 in order to get the source back - since you are doing this automatically it doesn't matter if the source is obfuscated.
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.
来源:https://stackoverflow.com/questions/47380733/how-can-i-inject-code-in-python-programs-so-that-they-can-print-the-conditions-i