ast
(抽象语法树)模块。
使用
ast.NodeVisitor
,可以遍历源树并显示信息,例如每个节点的名称,如下所示:
class MyAST(ast.NodeVisitor):
def visit_ClassDef(self, node):
print(node.col_offset * " " +node.name)
self.generic_visit(node)
def visit_FunctionDef(self, node):
print(node.col_offset * " " + node.name)
self.generic_visit(node)
然后可以将其用于任何代码片段,如下所示:
tree = ast.parse(open("/path/to/file.py").read())
MyAST().visit(tree)
这将输出类似的内容(例如,在 requests 包中的 models.py 上使用):
RequestEncodingMixin
path_url
_encode_params
_encode_files
RequestHooksMixin
register_hook
deregister_hook
Request
__init__
__repr__
prepare
(...)
我想知道对于给定的节点,它的完整“路径”。在上面的输出示例中,当我位于
FunctionDef
节点 deregister_hook
时,我想知道它的父节点是 ClassDef
RequestHooksMixin
,以便我可以输出类似 RequestHooksMixin.deregister_hook
的内容。
ast.NodeVisitor
的设计并未考虑嵌套级别,因此它不是使用基于级别的缩进生成输出的最佳工具。
相反,您可以使用
ast.iter_child_nodes
递归遍历每个节点的直接子节点,并输出该节点并在它是类或函数时增加缩进级别
import ast
def build_tree(node):
def _visit(node, level=0):
if isinstance(node, (ast.ClassDef, ast.FunctionDef)):
yield node.name, level
level += 1
for child in ast.iter_child_nodes(node):
yield from _visit(child, level)
return '\n'.join(f'{" " * level}{name}' for name, level in _visit(node))
这样:
source = '''
class Foo:
def method1(self):
pass
def method2(self):
pass
class Bar:
def method1(self):
pass
def method2(self):
pass
'''
print(build_tree(ast.parse(source)))
输出:
Foo
method1
method2
Bar
method1
method2