如何用asttokens在Python中反解析AST树并保留代码格式?
用asttokens保留AST修改后的代码格式
可以借助asttokens实现格式保留,核心思路是利用asttokens关联AST节点与原始代码的字符位置信息,只替换修改过的节点内容,其余原始格式(包括空行、注释、自定义缩进)保持不变,而不是用ast.unparse重新生成整个代码(后者会彻底丢失格式)。
具体步骤和示例如下:
- 用
ASTTokens绑定原始代码与AST树,让每个节点携带原始代码中的位置和文本信息 - 修改AST节点后,通过节点的位置信息定位到原始代码中的对应片段,替换为修改后的内容
- 保留未修改部分的原始格式
import ast from asttokens import ASTTokens # 原始代码,包含空行 code_str = """ print('1') print('2') """ # 绑定代码与AST,获取带位置信息的节点 atok = ASTTokens(code_str, parse=True) tree = atok.tree # 示例:修改第一个print语句的参数 for node in ast.walk(tree): if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == 'print': # 修改第一个print的参数为'modified 1' node.args[0].s = 'modified 1' break # 生成修改后的代码:只替换修改的节点,其余保留原始格式 new_code = atok.replace(node, ast.unparse(node)) # 输出对比 print("原始代码:") print(repr(code_str)) print("\n修改后代码:") print(repr(new_code))
运行后输出会保留原始的空行:
原始代码: "\nprint('1')\n\nprint('2')\n" 修改后代码: "\nprint('modified 1')\n\nprint('2')\n"
注意事项
- 这种方法适合局部节点修改,如果是大规模结构修改(比如新增/删除语句块),需要额外处理节点的位置偏移,但asttokens也提供了
get_text、span等方法辅助定位 - ast.unparse仅用于生成单个修改节点的代码文本,整体代码是基于原始内容替换而来,所以能保留所有原始格式信息
内容的提问来源于stack exchange,提问作者Antunes
相关产品推荐
相关产品推荐

