python ast NodeTransformer Transformer代码转换 代码插桩 新增node节点 编译生成新函数 类内函数更新_ast

在这里插入图片描述

感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的:

① 2000多本Python电子书(主流和经典的书籍应该都有了)

② Python标准库资料(最全中文版)

③ 项目源码(四五十个有趣且经典的练手项目及源码)

④ Python基础入门、爬虫、web开发、大数据分析方面的视频(适合小白学习)

⑤ Python学习路线图(告别不入流的学习)

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!


import ast, astor, inspect

# 测试函数
def test\_func(a,b):
    d = a + 2
    f = b + 5
    o = d + f
    return o

# 代码转换pass
class dump\_trans(ast.NodeTransformer):
    def visit\_Assign(self, node):
        dump_code = "print({})".format(node.targets[0].id)
        dump_node = ast.parse(dump_code).body[0]
        return node, dump_node

# 获取原函数ast
tast = ast.parse(inspect.getsource(test_func)).body[0]

# 进行代码插入
dt = dump_trans()
ntast = dt.visit(tast)

# ast 转换成 源代码 str
new_code = astor.to_source(ntast)
print(new_code)
'''
def test\_func(a,b):
 d = a + 2
 print(d)
 f = b + 5
 print(f)
 o = d + f
 print(o)
 return o
'''

# 执行新代码 编译 生成 新函数对象
local={}
exec(new_code, {}, local)

print(local)

new_f = local["test\_func"]

# 执行新函数
new_f(6, 9.0)
# 会有打印信息

装饰器内实现代码插桩 类内函数更新

import ast, astor, inspect

# 获取函数源代码
def get\_func\_code(func):
    lines = inspect.getsource(func).split('\n')
    col_lead = len(lines[0]) - len(lines[0].lstrip(" "))
    lines = [c[col_lead:] for c in  lines]
    code_str = "\n".join(lines)
    return code_str

# dump runtime 函数
def dump(name, var):
    print(name + " : ", var)

class inject\_dump(ast.NodeTransformer):
    def \_\_init\_\_(self, global_val):
        self.global_val = global_val
        self.trans_func = {}

    def visit\_Assign(self, node):
        node.value = self.visit(node.value)
        dump_code = "dump(\'{}\', {})".format(node.targets[0].id, node.targets[0].id)
        dump_node = ast.parse(dump_code).body[0]
        return node, dump_node
    
    def visit\_Call(self, node):
        if isinstance(node.func, ast.Attribute) and isinstance(node.func.value, ast.Name) and\
            node.func.value.id == "self" and "self" in self.global_val:
            sub_func = getattr(self.global_val["self"], node.func.attr)
            ij_dump = inject_dump(self.global_val)
            fast = ast.parse(get_func_code(sub_func)).body[0]
            nfast = ij_dump.visit(fast)
            new_code = astor.to_source(nfast)
            print(new_code)
            local = {}
            exec(new_code, self.global_val, local)
            new_func = local[sub_func.__name__]
            # 更新类内的子函数 已经是非对象方法
            setattr(self.global_val["self"], sub_func.__name__, new_func)
            # 加 self参数
            return ast.Call(node.func, [ast.Name("self", node.func.ctx)] + node.args, node.keywords)
            
def transf(func):
    def \_deco(\*args, \*\*kwargs):
        funn_args = inspect.signature(func)
        global_val={"dump":dump,}
        if "self" in funn_args.parameters:
            print(args[0])
            global_val["self"] = args[0]
            print(getattr(args[0],"s"))
        t = inject_dump(global_val)
        fast = ast.parse(get_func_code(func)).body[0]
        fast.decorator_list = [] # de decorate
        nfast = t.visit(fast)
        print(getattr(args[0],"s"))
        #print(ast.dump(nfast))


**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化学习资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618317507)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值