问题描述
我正在使用 sys.set_trace(..)
对 python 代码执行字节码分析。
更具体地说,我设置了每次执行字节码时触发的跟踪器函数。
对于我的分析,我需要获取带有操作码 "STORE_ATTR"
的字节码将在其上存储值的对象。
例如。我有这个字节码:
Instruction(opname='STORE_ATTR',opcode=95,arg=9,argval='pos',argrepr='pos',offset=188,starts_line=None,is_jump_target=False)
看到这一点后,解释器将尝试从数据堆栈中弹出顶部元素,以便在其中存储一个值。 有没有办法让我访问该对象?是否有类似 TOP() 函数的 API,我可以从跟踪器中调用它并获取当前正在执行的帧堆栈的顶部值?
解决方法
遗憾的是,此类信息无法通过 Python 访问,但您可以使用 C API 来实现。这里的另一个问题是,这高度依赖于您拥有的 Python 版本。以下内容适用于 Python 3.8.5
,但稍加修改也适用于其他版本。
等效的 PyEval_SetTrace
可以访问 PyFrameObject
类的 f_stacktop
字段。此字段由 ceval.c
处的 TOP()
使用。
您还可以验证 f_stacktop
没有暴露给 Python frame
类 here。
在这里你可以看到一个代码示例,它可以访问当前帧的 TOS:
int tracefunc(PyObject *obj,PyFrameObject *frame,int what,PyObject *arg) {
[...]
PyObject **stack_pointer = frame->f_stacktop;
PyObject *tos = stack_pointer[-1];
[...]
}