给定AST,是否有获取源代码的可用库?

18 投票
4 回答
5508 浏览
提问于 2025-04-16 04:28

有没有办法把给定的Python抽象语法树(AST)转换成源代码呢?

这里有一个很好的例子,展示了如何使用Python的ast模块,特别是NodeTransformer。我在寻找一种方法,可以把生成的AST再转换回源代码,这样就可以直观地查看修改的内容。

4 个回答

5

我发现了一个很不错的第三方库:astunparse,它是基于Ned在他的回答中推荐的unparse.py。下面是一个例子:

import ast
import astunparse

code = '''
class C:
    def f(self, arg):
        return f'{arg}'

print(C().f("foo" + 'bar'))
'''

print(astunparse.unparse(ast.parse(code)))

运行后会得到:

class C():

    def f(self, arg):
        return f'{arg}'
print(C().f(('foo' + 'bar')))

另一个很酷的功能是astunparse.dump,它可以将代码对象以漂亮的格式打印出来:

astunparse.dump(ast.parse(code))

输出结果:

Module(body=[
  ClassDef(
    name='C',
    bases=[],
    keywords=[],
    body=[FunctionDef(
      name='f',
      args=arguments(
        args=[
          arg(
            arg='self',
            annotation=None),
          arg(
            arg='arg',
            annotation=None)],
        vararg=None,
        kwonlyargs=[],
        kw_defaults=[],
        kwarg=None,
        defaults=[]),
      body=[Return(value=JoinedStr(values=[FormattedValue(
        value=Name(
          id='arg',
          ctx=Load()),
        conversion=-1,
        format_spec=None)]))],
      decorator_list=[],
      returns=None)],
    decorator_list=[]),
  Expr(value=Call(
    func=Name(
      id='print',
      ctx=Load()),
    args=[Call(
      func=Attribute(
        value=Call(
          func=Name(
            id='C',
            ctx=Load()),
          args=[],
          keywords=[]),
        attr='f',
        ctx=Load()),
      args=[BinOp(
        left=Str(s='foo'),
        op=Add(),
        right=Str(s='bar'))],
      keywords=[])],
    keywords=[]))])
7

从Python 3.9开始,ast模块提供了一个叫做unparse的功能:

这个功能可以把一个ast.AST对象转换成一段代码字符串,如果用ast.parse()再解析这段字符串,就能得到一个相同的ast.AST对象。

14

Python的源代码里有一个实现,具体在Demo/parser目录下的unparse.py文件。

编辑说明: 从Python 3.9开始,新增了ast.unparse()这个功能,因此unparse.py文件已经被删除,所以上面的链接更新到了3.8版本。

撰写回答