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

发布于 2024-07-27 04:28:22 字数 569 浏览 3 评论 0原文

我喜欢 _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 以及可能为其执行的其他函数调用。

I like the options offered by the _ast module, it's really powerful. Is there a way of getting the full AST from it?

For example, if I get the AST of the following code :

import os
os.listdir(".")

by using :

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

the body of the ast object will have two elements, an import object, and a expr object. However, I'd like to go further, and obtain the AST of import and listdir, in other words, I'd like to make _ast descend to the lowest level possible.

I think it's logical that this sort of thing should be possible. The question is how?

EDIT: by the lowest level possible, I didn't mean accesing what's "visible". I'd like to get the AST for the implementation of listdir as well: like stat and other function calls that may be executed for it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

女皇必胜 2024-08-03 04:28:23

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

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

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

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

要方便地访问树中的所有节点,在 2.6 中,请使用模块 ast(无前导下划线)并根据需要子类 ast.NodeVisitor(或等效地递归地使用 ast.iter_child_nodesast.iter_fields 根据需要)。 当然,如果您由于某种原因陷入 2.5 版本,这些助手可以在 _ast 之上用纯 Python 实现。

You do get the whole tree this way -- all the way to the bottom -- but, it IS held as a tree, exactly... so at each level to get the children you have to explicitly visit the needed attributes. For example (i'm naming the compile result cf rather than ast because that would hide the standard library ast module -- I assume you only have 2.5 rather than 2.6, which is why you're using the lower-level _ast module instead?)...:

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

This is what tells you that the import statement is importing name os (and that one only because 1 is the lengths of the .names field of .body[0] which is the import).

In Python 2.6's module ast you also get helpers to let you navigate more easily on a tree (e.g. by the Visitor design pattern) -- but the whole tree is there in either 2.5 (with _ast) or 2.5 (with ast), and in either case is represented in exactly the same way.

To handily visit all the nodes in the tree, in 2.6, use module ast (no leading underscore) and subclass ast.NodeVisitor as appropriate (or equivalently use ast.iter_child_nodes recursively and ast.iter_fields as needed). Of course these helpers can be implemented in pure Python on top of _ast if you're stuck in 2.5 for some reason.

找回味觉 2024-08-03 04:28:23
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
'.'

华泰

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文