【问题标题】:Converting string typed Abstract Syntax Tree(AST) to Python Code?将字符串类型的抽象语法树(AST)转换为 Python 代码?
【发布时间】:2020-07-24 11:41:23
【问题描述】:

我正在处理 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 树转换回代码的东西。

【问题讨论】:

标签: python parsing compiler-construction abstract-syntax-tree


【解决方案1】:

有几种方法可以将 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]'

当然,由于使用了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]'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多