为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

天涯尽头无女友 2023-10-18 21:35:53
我想不仅将 NodeTransformer 应用于当前文件的 AST,而且还应用于导入的任何代码。如果运行下面的代码,您会注意到转换器可以工作,但仅适用于读取和解析的单个文件。我将如何修改此代码以将转换器应用于解析代码中的任何导入?a.py:from b import qdef r(a):    return q(a) + 5b.py:def q(n):    return r(n + 1)def r(n):    return nMain.py:import astimport astorclass 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 nodeparsed_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) + 511但我希望它能产生:Doing: return q(a) + 5Doing: return r(n + 1)Doing: return n11
查看完整描述

1 回答

?
catspeake

TA贡献1111条经验 获得超0个赞

好吧,虽然花了一些功夫,但我明白了(woo):


import ast

import astor

import importlib

import sys


class trivial_transformer(ast.NodeTransformer):


    def processImport(self, imp):

        if imp not in sys.modules:

            spec = importlib.util.find_spec(imp)

            helper = importlib.util.module_from_spec(spec)

            parsed_dep = ast.fix_missing_locations(self.visit(ast.parse(spec.loader.get_source(imp))))

            exec(compile(parsed_dep, imp, 'exec'), helper.__dict__)

            sys.modules[imp] = helper


    def visit_ImportFrom(self, node):

        self.processImport(node.module)

        return node


    def visit_Import(self, node):

        for i in node.names:

            self.processImport(i.name)

        return node


    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



init = 'a'

trivial_transformer().processImport(init)


import a

a.r(5)


查看完整回答
反对 回复 2023-10-18
  • 1 回答
  • 0 关注
  • 48 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信