将以字符串形式表示的抽象语法树(AST)转换为Python代码?

4
我正在处理 Python 代码解析后的 AST 字符串。目前,我想将一些小的树形结构转换回代码以进行分析。
import ast
ast_string = ast.dump(ast.parse("[1,2,3]"))
print(ast_string)
# 'Module(body=[Expr(value=List(elts=[Num(n=1), Num(n=2), Num(n=3)], ctx=Load()))])'

现在,我想将这个Module(body=[Expr(value=List(elts=[Num(n=1), Num(n=2), Num(n=3)], ctx=Load()))])转换回代码。

示例:

def ast_to_code(ast_string):
   ....

code = ast_to_code(ast_string)
print(code) # [1,2,3]

提前感谢。我在网上搜索了不同的库,可以接受解析树对象,然后将其转换回代码。但我找不到能够将任何AST树转换为字符串代码的东西。


1
请查看我的回答以了解如何实现此操作:https://dev59.com/Sm025IYBdhLWcg3wvIgo#5834775 - Ira Baxter
Nomiluks:我也遇到了同样的问题,你找到任何Python解决方案了吗? - berniethejet
1
你尝试过使用libcst吗?我能够从节点生成代码。这里也有相关的帖子:https://dev59.com/RLzpa4cB1Zd3GeqPDArG - Nomiluks
1个回答

0
有几种方法可以将AST字符串转换回ast.AST对象。第一种解决方案是最短的,因为它涉及将原始字符串中的ast.AST子类名称替换为它们的模块点查找,然后使用eval生成结果:
import ast, re
def ast_to_code(ast_string):
   return ast.unparse(eval(re.sub('\w+(?=\()', lambda x:f'ast.{x.group()}', ast_string)))

ast_string = ast.dump(ast.parse("[1,2,3]"))
print(ast_to_code(ast_string))
#even shorter option with star import:
from ast import *
print(ast.unparse(eval(ast.dump(ast.parse("[1,2,3]")))))

输出:

'[1, 2, 3]'

当然,上面的解决方案有点hackish并且相当不安全,因为使用了eval。另一种选择是将AST字符串(本身是有效的Python语法)解析为ast对象,然后遍历结果并创建一个新的ast对象:

import ast
ast_string = ast.dump(ast.parse("[1,2,3]"))
def to_ast(d):
   if isinstance(d, ast.Call):
      return getattr(ast, d.func.id)(*map(to_ast, d.args), 
                     **{i.arg:to_ast(i.value) for i in d.keywords}, **{'lineno': None, 'col_offset': None, 'end_lineno': None, 'end_col_offset': None})
   if isinstance(d, ast.List):
      return list(map(to_ast, d.elts))
   return d.value

def ast_to_code(ast_string):
   return ast.unparse(to_ast(ast.parse(ast_string).body[0].value))

print(ast_to_code(ast_string))

输出:

'[1, 2, 3]'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接