Python code reflection and modification

别来无恙 提交于 2021-01-27 14:50:35

问题


Perhaps I'm not using the proper term, but I'm looking to take a block of Python code (in Python), get the token tree for the code, make some kind of modification, and re-assemble it to Python.

For instance, consider this block of code:

def x(y):
    b = 2
    if y == b:
        foo(y)

I would like to be able to take this and programmatically do this:

def x(y):
    b = 2
    if y == b:
        bar(y)

I can't imagine that there's not a library that does something like this. Thanks in advance.

EDIT

Perhaps I wasn't entirely clear. I'm looking for a tool to read and manipulate arbitrary code, not code that I'm writing. I'd like to be able to modify code on-the-fly. The project I'm working on is a test app: it uses the Netflix philosophy to try to randomly break the functionality of an app in as many ways as it can, running the test suite each time. When the tests don't fail, there's an indication that there's either a gap in code coverage and/or the code is dead.


回答1:


I was curious about this so I looked into the link Apalala posted, here is what I came up with:

from token import NAME
from tokenize import generate_tokens, untokenize
from StringIO import StringIO

source = """def x(y):
    b = 2
    if y == b:
        foo(y)"""
result = []
tokens = generate_tokens(StringIO(source).readline)
for toknum, tokval, _, _, _ in tokens:
    if toknum == NAME and tokval == "foo":
        tokval = "bar"
    result.append((toknum, tokval))

print untokenize(result)

And the result is:

def x (y ):
    b =2 
    if y ==b :
        bar (y )

Yeah I know, the spacing is ugly. I could not figure out how to maintain the format from the original code, but as far as functionality goes, this does what you want.




回答2:


In Python functions can be passed just like any other object so you should be able to do something like:

def x(fx, y):
    b = 2
    if y == b:
        fx(y)

and then call:

x(foo, y)

or

x(bar, y)

Here's a stripped down, tested snippet (v 3.1) that demonstrates the concept w/o any bizlogic, just sample execution and arbitrary numeric manipulation:

def x(fx, y): return fx(y)
def foo(x): return x
def bar(x): return x+1

print(x(foo,1))
print(x(bar,1))

output:

>>> 
1
2



回答3:


You can change your program classes by reflection like this


    class A(object):
        def __init__(self, x):
            self.x = x
        def show(self):
            print self.x

    def chglobals():
        import newmod
        reload(newmod)
        o = newmod.A(0)
        globals()['A'] = o.__class__

    def main():
        a = A(10)
        a.show()

        #change and wirte new code
        src = inspect.getsource(a.__class__)
        src = src.replace("print self.x", 'print "foo" ')
        text_file = open("newmod.py", "w")
        text_file.write(src)
        text_file.close()
        chglobals()

        #new istances
        b = A(20)
        b.show()

        #convert old istances
        a.__class__ = b.__class__
        a.show()


    main()




回答4:


I'm going to have to guess about the usecase here, but I'll assume that at a certain point in time you want to switch for 1 function to the other. Doing this can be done relatively easily be using a dictionary filled with functions. For example:

def foo(x): return x
def bar(b): return x+1
fn = { 'foo': foo, 'bar': bar }

def x(y):
    b = 2
    func = 'foo'
    if y == b:
        fn[func](y)

This will let you choose which function you want based simply on the dictionary key. You can do so simply by changing the value of func (for example to 'bar').



来源:https://stackoverflow.com/questions/4764480/python-code-reflection-and-modification

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!