Python 中处理自身语法树应使用 ast 模块而非已弃用的 parser 模块;后者仅支持过时的解析树,无法正确处理 walrus 运算符、match 语句等新语法,且自 Python 3.12 起已被移除。

Python 没有叫 parser 的标准模块能直接处理“Python自身的语法树”——你真正需要的是 ast 模块,不是 parser。
为什么不能用 parser 模块解析 Python 代码?
parser 是一个已弃用的旧模块(自 Python 3.9 起标记为 deprecated,3.12+ 已移除),它底层调用的是过时的 pgen 解析器,只支持生成“解析树”(parse tree),而非结构清晰、语义完整的抽象语法树(AST)。它不能可靠反映 Python 3.x 的实际语法(比如 walrus 运算符 :=、类型注解、match 语句等都会出错或被忽略)。
真正稳定、官方推荐、与 CPython 解析器同步更新的是 ast 模块。
用 ast.parse() 获取合法 Python 代码的 AST
这是最常用入口:把源码字符串或文件内容转成 ast.AST 对象树。
立即学习“Python免费学习笔记(深入)”;
-
ast.parse("x = 1 + 2")返回一个Module节点,其.body是包含Assign节点的列表 - 必须传入合法 Python 语法;若含语法错误,抛出
SyntaxError(不是ValueError或其他) - 可选参数
mode控制返回节点类型:"exec"(默认,整个模块)、"eval"(单个表达式,如ast.parse("2+3", mode="eval")返回Expression)、"single"(交互式语句,少用) - 注意缩进和换行:多行代码需保持原始缩进,否则
SyntaxError: unexpected indent
遍历和修改 AST 要用 ast.NodeVisitor 和 ast.NodeTransformer
直接递归访问 node.body 容易漏掉嵌套结构(比如函数体里的 if 分支、列表推导中的条件)。标准做法是继承这两个基类:
-
ast.NodeVisitor:只读遍历,重写visit_XXX方法(如visit_Assign、visit_Call)处理特定节点;不改原树 -
ast.NodeTransformer:继承自NodeVisitor,但允许返回新节点或None(删除该节点);返回值会自动替换原位置 - 所有节点类型名来自 AST 规范,可用
ast.dump(node, indent=2)快速查看结构(调试必备) - 修改后需用
compile()才能执行:code = compile(modified_ast, filename="<string>", mode="exec")</string>,再exec(code)
常见坑:AST 节点字段名不等于源码关键字
比如你以为 if node.name == "x" 就能判断变量名?错。变量名存在 Name 节点的 .id 字段,而 Assign 节点的左值是 .targets(列表),右值是 .value;Call 的函数名在 .func,参数在 .args,关键字参数在 .keywords。
别靠猜字段名——用 ast.dump(node, include_attributes=True) 看清真实结构,再查 AST 抽象语法定义确认字段语义。很多 bug 来自把 .id 当成 .name,或把 .body 当成 .content。


















