如何在Python中获得完整的AST?

时间:2009-07-14 21:43:03

标签: python abstract-syntax-tree

我喜欢 _ast 模块提供的选项,它非常强大。有没有办法从中获取完整的AST?

例如,如果我得到以下代码的AST:

import os
os.listdir(".")

使用:

ast = compile(source_string,"<string>","exec",_ast.PyCF_ONLY_AST)

ast 对象的主体将有两个元素,一个 import 对象和一个 expr 对象。但是,我想更进一步,获得 import listdir 的AST,换句话说,我想做 _ast 下降到可能的最低水平。

我认为这种事情应该是可行的,这是合乎逻辑的。问题是如何

编辑:在可能的最低级别,我并不意味着访问“可见”的内容。我想获得用于实现 listdir 的AST:例如 stat 以及可能为其执行的其他函数调用。

2 个答案:

答案 0 :(得分:8)

你确实以这种方式获得整棵树 - 一直到底部 - 但是,它被保存为一棵树,确切地说......所以在每个级别都要让孩子们必须明确地访问所需的属性。例如(我命名compile结果cf而不是ast,因为这会隐藏标准库ast模块 - 我假设你只有2.5而不是2.6,这就是为什么您正在使用较低级别的_ast模块吗?)...:

>>> cf.body[0].names[0].name
'os'

这就是告诉你导入语句导入名称os(而这只是因为1是.names .body[0]字段的长度{{1} }})。

在Python 2.6的模块import中,您还可以获得帮助,以便您更轻松地在树上导航(例如,通过ast设计模式) - 但是整个树都在2.5中(使用Visitor)或2.5(使用_ast),并且在任何一种情况下都以完全相同的方式表示。

为了方便地访问树中的所有节点,在2.6中,根据需要使用模块ast(无前导下划线)和子类ast(或者等效地使用递归ast.NodeVisitorast.iter_child_nodes作为需要)。当然,如果由于某种原因你被困在2.5中,这些助手可以在ast.iter_fields之上用纯Python实现。

答案 1 :(得分:5)

py> ast._fields
('body',)
py> ast.body
[<_ast.Import object at 0xb7978e8c>, <_ast.Expr object at 0xb7978f0c>]
py> ast.body[1]
<_ast.Expr object at 0xb7978f0c>
py> ast.body[1]._fields
('value',)
py> ast.body[1].value
<_ast.Call object at 0xb7978f2c>
py> ast.body[1].value._fields
('func', 'args', 'keywords', 'starargs', 'kwargs')
py> ast.body[1].value.args
[<_ast.Str object at 0xb7978fac>]
py> ast.body[1].value.args[0]
<_ast.Str object at 0xb7978fac>
py> ast.body[1].value.args[0]._fields
('s',)
py> ast.body[1].value.args[0].s
'.'

HTH