是否有任何钩挂CPython解释器的方法,以便每次函数创建(def
,lambda
)都会导致对我定义的过程的调用?不幸的是,sys.settrace
和sys.setprofile
并没有同时涵盖def
和lambda
。
Python 3.7似乎有f_trace_opcodes
...较早版本是否有任何选择?
答案 0 :(得分:4)
在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
的源代码,也可以检查字节码,以了解其中定义了函数,但是在定义时仍然无法正确调用钩子。NodeTransformer
在每个def
之前或之后使用对某些函数 2 的调用, lambda
节点,然后编译转换后的树。但您也可以在每个MAKE_FUNCTION
之前或之后,在bytecode
或byteplay
的字节码级别上执行此操作。 3 pdb
而不是编写自己的调试器。我不确定这是否还会有所帮助,因为pdb
首先没有办法单步执行表达式的一部分。MAKE_FUNCTION
循环的ceval
处理程序中添加一个断点。当然,您的代码在调试器的解释器中-可以是用于gdb
和lldb
的Python,但仍不是您要调试的相同 Python解释器。而且,尽管可以将代码递归地评估到调试的解释器中(或触发其pdb
),但这并不容易,而且在执行代码时会在各处进行段隔离。 1。理解(2.x中的列表理解除外)是通过定义然后调用一个函数来实现的。因此,任何依赖MAKE_FUNCTION
操作码或类似方法的方法也将在理解上触发,而那些依赖源或AST解析的方法则不会(当然,除非您明确地这样做)。
2。显然,您还需要在每个模块的顶部插入一个import
才能使该功能可用,或者将该功能插入到内置模块中。
3。还有MAKE_CLOSURE
,用于Python的早期版本。