将Python AST编译为方法
我最近在用Python玩AST(抽象语法树)。我想在程序运行时通过改变AST来修改方法。
我可以用inspect.getsource()
获取一个预编译方法的源代码,并且可以通过AST访问器来按需要修改AST。
这可能有点天真,但我希望能编译这个AST,做类似这样的事情:
myClass.method.__func__.__code__ = compile(newAST, '<string>', 'exec')
不过,编译时只接受以ast.Module为根的AST。有没有办法只编译一个ast.FunctionDef,或者从编译后的(其他部分为空的)模块代码中获取函数的代码对象呢?
如果能给我一些关于这方面的信息就太好了。我看到的AST示例大多只处理简单的表达式。
我意识到我只需要在一个命名空间中执行这个模块,这样我就能访问到正常的结构了。所以模式是:
src = inspect.getsource(myClass.myMethod)
astFromSrc = ast.parse(unindent(src)) # need to remove extra indent from method
transform(astFromSrc.body) # transform the AST as you need
ast.fix_missing_locations(astFromSrc) # fix up line numbers etc
compiled = compile(astFromSrc, '<string>', 'exec') # compile the module AST
####### From here is the part I was missing
myScope = {} # make an empty namespace
exec compiled in myScope # now myScope contains a proper compiled function
# Now replace the original with the modified version
myClass.myMethod.__func__.__code__ = myScope['myMethod'].__code__
但现在我有另一个问题:如何把这个过程融入到正常的Python构建流程中,这样修改只需要做一次,以后就可以从.pyc文件中加载?
1 个回答
1
你不应该在自己的回答里问新问题,而是应该单独提一个新问题。
注意,你的第一个和第二个问题有点矛盾。最开始你想在运行时做一些事情,后来又想把这些内容写入文件,这样就不用重复做了。请明确说明你的最终目标,这样我们才能清楚地知道你想要什么。
听起来你可以在修改了一个文件的抽象语法树(AST)后,创建一个新的 .py 文件,就像在解析一个 .py 文件,读取 AST,修改它,然后写回修改后的源代码中所解释的那样。
然后你可以通过编译新创建的 py 文件来获得你的 pyc 文件。