gpt4 book ai didi

python - 有什么方法可以在 CPython 中创建函数时执行代码?

转载 作者:太空宇宙 更新时间:2023-11-03 14:42:29 29 4
gpt4 key购买 nike

有什么方法可以 Hook CPython 解释器,以便每个函数创建(deflambda)都会调用我定义的过程?不幸的是,sys.settracesys.setprofile 似乎没有涵盖 deflambda

更新:

Python 3.7 似乎有 f_trace_opcodes...是否有针对早期版本的选项?

最佳答案

在 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)

但是,如果您做不到……您可以做一些更复杂的事情,具体取决于您想要这样做的原因,但没有一件是简单的:

  • 使用 跟踪,检查代码直到下一行。这对于 def 来说是微不足道的,但是对于 lambda(和理解1)来说这将是一个很大的痛苦,因为 lambda (甚至五个)可以出现在语句的中间。您可以ast.parse 源代码或检查字节码,以确定其中定义了函数,但仍然无法在定义时调用您的 Hook 。
  • 不使用跟踪,而是编写一个导入 Hook ,在导入时修改代码。执行此操作的简单方法可能是在 AST 级别:解析源代码后,使用 NodeTransformer在每个 deflambda 节点之前或之后注入(inject)对某些函数 2 的调用,然后编译转换后的树。但是您也可以使用 bytecode 在字节码级别执行此操作或 byteplay ,在每个 MAKE_FUNCTION 之前或之后。3
  • 编写pdb 脚本而不是编写您自己的调试器。我不确定这是否有帮助,因为 pdb 无法首先逐步执行表达式的一部分。
  • 调试 CPython 本身,并在调用您的代码的 ceval 循环中的 MAKE_FUNCTION 处理程序中添加一个断点。当然,您的代码在调试器的解释器中 — 对于 gdblldb 可以是 Python,但它仍然不是您的相同 Python 解释器重新调试。而且,虽然可以在调试的解释器中递归评估代码(或触发其 pdb),但这并不容易,而且您在解决问题时到处都是段错误。

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

<子>2。显然,您还需要在每个模块的顶部注入(inject)一个 import 以使该功能可用,或者将该功能注入(inject)内置模块。

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

关于python - 有什么方法可以在 CPython 中创建函数时执行代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52238507/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com