5

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

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

import os
os.listdir(".")

通过使用 :

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

ast对象的主体将有两个元素,一个import对象和一个expr对象。但是,我想更进一步,获取importlistdir的 AST,换句话说,我想让_ast降到可能的最低级别。

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

编辑:尽可能最低级别,我并不是说要访问“可见”的内容。我也想获得用于实现listdir的 AST :比如stat和其他可能为其执行的函数调用。

4

2 回答 2

8

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

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

这就是告诉您 import 语句正在导入 name 的os原因(那只是因为 1 是.names字段的长度,.body[0]import)。

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

为了方便地访问树中的所有节点,在 2.6 中,使用模块 ast(没有前导下划线)和ast.NodeVisitor适当的子类(或等效地使用ast.iter_child_nodes递归并ast.iter_fields根据需要)。当然,_ast如果您由于某种原因被困在 2.5 中,这些帮助程序可以在纯 Python 中实现。

于 2009-07-14T21:55:19.113 回答
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
'.'

高温高压

于 2009-07-14T21:49:38.423 回答