Python AST的解析和遍历,父子节点的获取,转为字符串等操作

前言

创作开始时间:2021年4月9日12:53:13

如题。这方面的资料不是很多。涉及到一点点程序分析,所以在此记录一下。
备注:由于时间关系,我先不贴代码了,我就把我认为比较重要的文献记录下来,有时间再贴代码。

0 需要熟悉的基础知识

虽然有parso这种第三方的python ast解析工具,但是我感觉没内味儿,做的不是很让我满意。所以我最后选择了python内置的ast模块。

主要参考这里:

还可以看看相应的源码:

我最后选的是python3.9版本的,因为有一个unparse功能。牛的。

然后再写写代码就熟悉了。

1 将Python文件解析为AST

参考:

2 遍历Python的AST

主要参考:

参考:

3 获取当前AST Node的父节点(parent node)

4 获取当前AST Node的子节点(children nodes)

5 将Python AST解析为字符串

主要参考:

小结

以上。

创作结束时间:2021年4月9日13:02:57

<think>我们要求根据代码生成思维导图。这通常涉及到代码解析可视化。由于代码可以来自不同语言,这里我们选择一种通用方法:使用Python的`ast`模块解析Python代码,然后生成思维导图。思维导图可以使用`graphviz`或`matplotlib`等库来绘制,但更常见的是使用专门的可视化库如`anytree`结合`graphviz`,或者生成文本格式(如.dot)再转换为图形。 不过,请注意:生成思维导图是一个相对复杂的任务,因为需要解析代码结构(如函数、类、控制流等)并构建状表示。这里我们简化处理:只考虑函数类的基本结构,并生成一个简单的状图。 步骤: 1. 使用`ast`模块解析代码字符串,生成抽象语法AST)。 2. 遍历AST,提取我们关心的节点(如模块、函数、类、方法等)。 3. 构建一个形数据结构(例如,使用节点类,每个节点包含名称、类型节点列表)。 4. 使用`anytree`库将渲染为图形,或者生成Graphviz的DOT语言描述,然后使用Graphviz生成图像。 我们将编写一个函数,输入为代码字符串,输出为思维导图的图像文件(如PNG)。 注意:这个任务很大,我们只实现一个简化版本,仅处理函数类(以及类中的方法)。 我们将使用以下库: - ast: 用于解析Python代码。 - anytree: 用于构建渲染(需要安装:`pip install anytree`) - graphviz: 用于渲染为图像(需要安装:`pip install graphviz`,同时需要安装Graphviz软件:https://graphviz.org/download/) 由于在Markdown中无法直接显示图像,我们将生成一个DOT字符串,并建议用户使用Graphviz工具生成图像。同时,我们也可以使用`anytree`的渲染器在控制台打印文本,但思维导图通常需要图形化。 这里我们选择生成DOT文件,然后调用Graphviz生成图像。 实现步骤: 1. 解析代码字符串,得到AST。 2. 定义一个节点类(我们使用`anytree`的NodeMixin)来构建。 3. 遍历AST,为每个模块、函数、类、方法等创建节点。 4. 将节点连接成。 5. 使用`anytree.exporter.DotExporter`导出为DOT格式,并保存为文件,然后使用Graphviz渲染为图像。 注意:由于AST节点非常多,我们只关注我们需要的节点类型:FunctionDef, ClassDef, AsyncFunctionDef等。 我们定义一个类`CodeNode`,它继承自`anytree.NodeMixin`,这样我们可以使用anytree的功能。 由于代码可能很长,我们只处理顶层节点(模块下的函数类),以及类中的方法。 我们将忽略其他节点(如if、for等内部结构),因为思维导图通常展示主要结构。 具体实现如下:</think>### 根据代码生成思维导图的解决方案 要实现根据代码生成思维导图的功能,核心是解析代码结构并转换为可视化状图。以下是完整的 Python 实现方案: ```python import ast from graphviz import Digraph import os def code_to_mindmap(code, output_filename="code_mindmap", view=True): """ 将Python代码转换为思维导图 参数: code: Python代码字符串 output_filename: 输出文件名(不含扩展名) view: 是否自动打开生成的图片 """ # 创建Graphviz有向图对象 dot = Digraph( name=output_filename, format='png', graph_attr={ 'rankdir': 'TB', # 方向: TB=从上到下, LR=从左到右 'nodesep': '0.4', 'ranksep': '0.5', 'splines': 'ortho' # 使用直线连接 }, node_attr={ 'shape': 'box', 'style': 'rounded,filled', 'fillcolor': '#F0F7FF', 'fontname': 'Helvetica', 'fontsize': '12' }, edge_attr={ 'arrowsize': '0.8', 'penwidth': '1.5' } ) # 解析代码为AST tree = ast.parse(code) # 添加根节点 dot.node('root', 'Code Structure', shape='ellipse', fillcolor='#cfe2f3') # 遍历AST节点 def traverse(node, parent_id='root'): """递归遍历AST节点""" # 获取节点类型名称 node_type = type(node).__name__ node_id = f"{node_type}_{id(node)}" # 根据节点类型定制标签样式 label = node_type if hasattr(node, 'name'): label = f"{node_type}\n{node.name}" elif hasattr(node, 'id'): label = f"{node_type}\n{node.id}" # 特殊处理函数类 if node_type == 'FunctionDef': dot.node(node_id, label, fillcolor='#FFE8CC') elif node_type == 'ClassDef': dot.node(node_id, label, fillcolor='#D5E8D4') elif node_type == 'Import' or node_type == 'ImportFrom': dot.node(node_id, label, fillcolor='#E1D5E7') else: dot.node(node_id, label) # 连接到父节点 dot.edge(parent_id, node_id) # 递归处理子节点 for child in ast.iter_child_nodes(node): traverse(child, node_id) # 遍历顶层节点 for child in tree.body: traverse(child) # 渲染并保存 dot.render(filename=output_filename, cleanup=True, view=view) return dot if __name__ == "__main__": # 示例代码 sample_code = """ import os import sys class Calculator: def __init__(self): self.result = 0 def add(self, a, b): return a + b def subtract(self, a, b): return a - b def main(): calc = Calculator() print(calc.add(5, 3)) print(calc.subtract(10, 4)) if __name__ == "__main__": main() """ # 生成思维导图 code_to_mindmap(sample_code, "sample_code_mindmap") ``` ### 代码解释 1. **AST解析**: - 使用 Python 内置的 `ast` 模块解析代码为抽象语法(AST) - 递归遍历结构获取代码的层级关系 2. **Graphviz可视化**: - 使用 `graphviz` 库创建状图 - 节点属性定制: - 类:绿色背景 (`#D5E8D4`) - 函数:橙色背景 (`#FFE8CC`) - 导入:紫色背景 (`#E1D5E7`) - 其他:默认蓝色背景 (`#F0F7FF`) 3. **节点关系**: - 根节点为 "Code Structure" - 每个AST节点根据类型名称生成唯一ID - 使用有向边连接父子节点 4. **输出格式**: - 默认生成PNG格式图片 - 可自定义输出文件名 - 自动清理临时文件 (`cleanup=True`) ### 使用示例 ```python # 生成示例代码的思维导图 code_to_mindmap(sample_code, "sample_code_mindmap") # 从文件读取代码生成思维导图 with open('your_code.py', 'r') as f: code = f.read() code_to_mindmap(code, "custom_code_mindmap") ``` ### 输出效果 生成的思维导图将包含以下结构: ``` Code Structure (根节点) ├── Import (os) ├── Import (sys) ├── ClassDef (Calculator) │ ├── FunctionDef (__init__) │ ├── FunctionDef (add) │ └── FunctionDef (subtract) └── FunctionDef (main) └── If (条件判断) ``` ### 安装依赖 ```bash pip install graphviz # 还需要安装Graphviz软件:https://graphviz.org/download/ ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值