No obvious way of getting PyFrameObject inside a frame evaluation function in Python 3.11

Debuggers that rely on PEP 523 often need access to PyFrameObject. The most important reason is access to the f_trace field to assign a local tracing function.

Starting from Python 3.11, a frame evaluation function gets _PyInterpreterFrame* instead of PyFrameObject*. The documentation mentions that the _PyInterpreterFrame’s frame_obj field is initialized lazily.

After reading the CPython source code, I have found a few candidate functions for frame object initialization, and none of them does exactly what I would expect.

_PyFrame_GetFrameObject() calls _PyFrame_MakeAndSetFrameObject() which is not a part of public API. As a result, attempting to use it causes a linkage error.

PyEval_GetFrame() seems to return a frame object for the previous _PyInterpreterFrame. As far as I understand, it has something to do with the fact the interpreter frame that the frame evaluation function gets is incomplete (?)

PyThreadState_GetFrame() leads to the same result as PyEval_GetFrame().

Am I missing something? If it’s not possible anymore to access f_trace field from a frame evaluation function, what’s an alternative?

1 Like

If you are writing a PEP based debugger in C, you probably want to operate on the _PyInterpreterFrame struct, rather than the PyFrameObject.

I’ve opened Issue #103609 to track the issue of PyEval_GetFrame()returning the previous frame.

Thank you for the reply and for opening the issue, Mark. I’d be happy to interact only with _PyInterpreterFrame, but it doesn’t allow setting the frame local tracing function. Or could you suggest any workaround?