Python 类型化ast节点评估 前言

Python 类型化ast节点评估 前言,python,python-3.x,abstract-syntax-tree,Python,Python 3.x,Abstract Syntax Tree,有一个用于跨Python AST解析和处理(例如,在1中) 问题 我想知道是否有一种方法可以像编译标准节点一样编译节点 因为这是有效的 import ast code = compile(ast.parse('print("Hello World!")'), '<ast>', 'exec') eval(code) # Hello World! 导入ast code=compile(ast.parse('print(“Hello World!”),'用于在ty

有一个用于跨Python AST解析和处理(例如,在1中)

问题 我想知道是否有一种方法可以像编译标准节点一样编译节点

因为这是有效的

import ast

code = compile(ast.parse('print("Hello World!")'), '<ast>', 'exec')
eval(code)  # Hello World!
导入ast
code=compile(ast.parse('print(“Hello World!”),'用于在
typed\u ast.ast27
typed\u ast.ast3
转换之间进行转换,但找不到类似的
typed\u ast.ast3
->
ast
转换

我也知道,但它会将源代码创建为字符串,这不是一个选项,因为我使用了一些使AST
可编译但不可解析的黑客

最后,还有哪些医生这么说

…如果需要求值*注释字段*必须设置为False

所以看起来可能有一种方法可以评估生成的转储字符串?或者有一种方法可以从
ast
加载此字符串

或者我应该编写自己的
ast3.NodeTransformer
类来执行这种转换吗



1:

到目前为止,我使用自定义
ast3.NodeTransformer的解决方案(在Python3.5上测试)

试验
从输入的ast导入ast3
code=compile(TypedToPlain().visit(ast3.parse('print(“helloworld!”))),
“执行官”
eval(代码)#你好,世界!
在Python3.3上不起作用(在
ast.Call
字段中存在差异)
from typed_ast import ast3

code = compile(ast3.parse('print("Hello World!")'), '<ast>', 'exec')  # raises exception
eval(code)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: compile() arg 1 must be a string, bytes or AST object
import ast
from functools import partial
from itertools import chain

from typed_ast import ast3


def to_visitor(cls):
    def none(_):
        return None

    try:
        plain_cls = getattr(ast, cls.__name__)
    except AttributeError:
        # node type is not found in `ast` module, skipping
        return none

    def visit(self, node):
        node = self.generic_visit(node)
        result = plain_cls(*map(partial(getattr, node), plain_cls._fields))
        return ast3.copy_location(result, node)

    return visit


def to_subclasses(cls,
                  *,
                  deep=True):
    result = cls.__subclasses__()
    yield from result
    if not deep:
        return
    subclasses_factory = partial(to_subclasses,
                                 deep=deep)
    yield from chain.from_iterable(map(subclasses_factory, result))


class TypedToPlain(ast3.NodeTransformer):
    visitors = {'visit_' + cls.__name__: to_visitor(cls)
                for cls in set(to_subclasses(ast3.AST))}

    def __getattr__(self, name):
        return partial(self.visitors[name], self)

    def generic_visit(self, node):
        for field, old_value in ast3.iter_fields(node):
            if isinstance(old_value, list):
                new_values = []
                for value in old_value:
                    if isinstance(value, ast3.AST):
                        value = self.visit(value)
                        if value is None:
                            continue
                        elif not isinstance(value, ast.AST):
                            new_values.extend(value)
                            continue
                    new_values.append(value)
                old_value[:] = new_values
            elif isinstance(old_value, ast3.AST):
                new_node = self.visit(old_value)
                if new_node is None:
                    delattr(node, field)
                else:
                    setattr(node, field, new_node)
        return node
from typed_ast import ast3

code = compile(TypedToPlain().visit(ast3.parse('print("Hello World!")')),
               '<ast>', 'exec')
eval(code)  # Hello World!