无法按照您想要的方式操作,因为这不是AST的工作方式。
当解释器运行代码时,它将从源文件生成AST,并
解释该AST以生成Python对象。
一旦生成了这些对象,它们发生了什么与AST无关。
但是,可以获取首次生成对象的AST。
模块
inspect
允许您获取某些Python对象的源代码。
import ast
import importlib
import inspect
m = importlib.import_module('pprint')
s = inspect.getsource(m)
a = ast.parse(s)
print(ast.dump(a))
但是
getsource()
的命名很恰当。
如果我改变了
m
中某个变量(或任何其他对象)的值,它不会改变其源代码。
即使可以从对象重新生成AST,
some_magic()
也不会有一个单一的解决方案。
想象一下,在某个模块中有一个变量
x
,我在另一个模块中重新分配它:
# In some_module.py
x = 0
# In __main__.py
m = importlib.import_module('some_module')
m.x = 1 + 227
现在,
m.x
的值是
228
,但没有办法知道导致该值的表达式是什么(好吧,除非读取
__main__.py
的AST,但这很快会失控)。它是仅仅一个字面量吗?还是函数调用的结果?
如果您真的必须在修改模块的某个值后获取新的AST,则最好的解决方案是自己转换原始AST。您可以找到标识符获取其值的位置,并将赋值的值替换为您想要的任何内容。例如,在我的小例子中,
x = 0
由以下AST表示:
Assign(targets=[Name(id='x', ctx=Store())], value=Num(n=0))
要获取与我在
__main__.py
中重新分配匹配的AST,我需要将上述
Assign
节点的值更改为以下内容:
value=BinOp(left=Num(n=1), op=Add(), right=Num(n=227))
如果您想走这条路,我建议您查看Python AST节点转换器(ast.NodeTransformer)的文档,以及这本优秀的手册,它记录了您可以在Python AST中遇到的所有节点。请点击
ast.NodeTransformer和
Green Tree Snakes - the missing Python AST docs。
pickle
、JSON等序列化格式。 - juanpa.arrivillaga