我需要将修改后的python对象转储回源代码。所以我尝试找到一些东西将真正的python对象转换为python ast.Node(稍后在astor
lib中使用以转储源代码)
我想要的用法示例,Python 2:
import ast
import importlib
import astor
m = importlib.import_module('something')
# modify an object
m.VAR.append(123)
ast_nodes = some_magic(m)
source = astor.dump(ast_nodes)
请帮助我找到some_magic
答案 0 :(得分:2)
没有办法做你想做的事,因为这不是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))
# Prints the AST of the pprint module
但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))
为了使AST符合我在__main__.py
中所做的重新分配,我必须更改上述{{1}}节点的值,如下所示:
Assign
如果您想这样做,我建议您查看Python的AST节点转换器文档(ast.NodeTransformer),以及记录您在Python ASTs中可以遇到的所有节点的优秀手册{ {3}}