有没有办法在CPython中执行函数创建代码?

2024-06-24 12:33:56 发布

您现在位置:Python中文网/ 问答频道 /正文

有没有办法钩住CPython解释器,以便每次函数创建(deflambda)都会导致对我定义的过程的调用?^不幸的是,{}和sys.setprofile似乎不能同时涵盖deflambda。你知道吗

更新:

Python3.7似乎有f_trace_opcodes。。。早期版本有什么选择吗?你知道吗


Tags: lambda函数版本定义过程defsystrace
1条回答
网友
1楼 · 发布于 2024-06-24 12:33:56

在3.7之前的版本中没有与opcode跟踪等价的东西。如果有的话,这个特性本来就不会添加到3.7中。你知道吗

如果您可以升级到3.7,那么您想要的很简单:

def tracefunc(frame, event, arg):
    if event == 'call':
        frame.f_trace_opcodes = True
    elif event == 'opcode':
        if frame.f_code.co_code[frame.f_lasti] == dis.opmap['MAKE_FUNCTION']:
            makefunctiontracefunc(frame)
    return tracefunc
sys.settrace(tracefunc)

但是如果你不能…你可以做很多更复杂的事情,这取决于你想要这个的理由,但是没有一件是简单的:

  • 使用line跟踪,检查代码直到下一行。这对于def来说是微不足道的,但是对于lambda(和理解1)来说,这将是一个巨大的痛苦,因为一个lambda(甚至其中五个)可能出现在语句的中间。您可以ast.parse源代码,或者检查字节码,以确定其中定义了函数,但是在定义时仍然无法正确调用钩子。你知道吗
  • 不使用跟踪,而是编写一个导入钩子,在导入代码时修改代码。实现这一点的简单方法可能是在AST级别:在解析源代码之后,使用^{}在每个deflambda节点之前或之后注入对函数2的调用,然后编译转换后的树。但是你也可以在字节码级别用^{}^{},在每个MAKE_FUNCTION之前或之后
  • 编写脚本pdb,而不是编写自己的调试器。我不确定这是否有帮助,因为pdb根本没有办法遍历表达式的一部分。你知道吗
  • 调试CPython本身,并在调用代码的ceval循环的MAKE_FUNCTION处理程序中添加断点。当然,您的代码在调试器的解释器中,它可以是gdblldb的Python解释器,但它仍然不是您正在调试的Python解释器。而且,虽然可以递归地将代码求值到已调试的解释器中(或者触发它的pdb),但这并不容易,而且您在计算代码时会到处都是错误。你知道吗

1。理解(2.x中的列表理解除外)是通过定义然后调用函数来实现的。因此,任何依赖于MAKE_FUNCTION操作码或类似操作码的方法也会触发理解,而那些依赖于源代码或AST解析的方法则不会(当然,除非您显式地这样做)。

2。显然,您还需要在每个模块的顶部插入一个import,以使该函数可用,或者将该函数插入到内置模块中。

3。和MAKE_CLOSURE,用于早期版本的Python。

相关问题 更多 >