如何将 ast.NodeTransformer 应用于导入?

我想不仅将 NodeTransformer 应用于当前文件的 AST,而且还应用于导入的任何代码。如果运行下面的代码,您会注意到转换器可以工作,但仅适用于读取和解析的单个文件。我将如何修改此代码以将转换器应用于解析代码中的任何导入?


a.py:


from b import q



def r(a):

    return q(a) + 5

b.py:


def q(n):

    return r(n + 1)



def r(n):

    return n

Main.py:


import ast

import astor



class trivial_transformer(ast.NodeTransformer):

    def visit_FunctionDef(self, node):

        body = []

        for line in node.body:

            body.append(

                ast.Expr(

                    ast.Call(func=ast.Name('print', ctx=ast.Load()),

                             args=[ast.Str(s="Doing: "+astor.to_source(line).strip())],

                             keywords=[])))

            body.append(self.generic_visit(line))

        node.body = body

        return node



parsed_ast = ast.fix_missing_locations(trivial_transformer().visit(ast.parse(open('a.py','r').read())))

g = {}

eval(compile(parsed_ast, '<source>', 'exec'), g)

print(g['r'](5))

这产生:


Doing: return q(a) + 5

11

但我希望它能产生:


Doing: return q(a) + 5

Doing: return r(n + 1)

Doing: return n

11


天涯尽头无女友
浏览 50回答 1
1回答

catspeake

好吧,虽然花了一些功夫,但我明白了(woo):import astimport astorimport importlibimport sysclass trivial_transformer(ast.NodeTransformer):&nbsp; &nbsp; def processImport(self, imp):&nbsp; &nbsp; &nbsp; &nbsp; if imp not in sys.modules:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; spec = importlib.util.find_spec(imp)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; helper = importlib.util.module_from_spec(spec)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; parsed_dep = ast.fix_missing_locations(self.visit(ast.parse(spec.loader.get_source(imp))))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exec(compile(parsed_dep, imp, 'exec'), helper.__dict__)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sys.modules[imp] = helper&nbsp; &nbsp; def visit_ImportFrom(self, node):&nbsp; &nbsp; &nbsp; &nbsp; self.processImport(node.module)&nbsp; &nbsp; &nbsp; &nbsp; return node&nbsp; &nbsp; def visit_Import(self, node):&nbsp; &nbsp; &nbsp; &nbsp; for i in node.names:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.processImport(i.name)&nbsp; &nbsp; &nbsp; &nbsp; return node&nbsp; &nbsp; def visit_FunctionDef(self, node):&nbsp; &nbsp; &nbsp; &nbsp; body = []&nbsp; &nbsp; &nbsp; &nbsp; for line in node.body:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; body.append(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ast.Expr(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ast.Call(func=ast.Name('print', ctx=ast.Load()),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;args=[ast.Str(s="Doing: "+astor.to_source(line).strip())],&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;keywords=[])))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; body.append(self.generic_visit(line))&nbsp; &nbsp; &nbsp; &nbsp; node.body = body&nbsp; &nbsp; &nbsp; &nbsp; return nodeinit = 'a'trivial_transformer().processImport(init)import aa.r(5)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python