Proposal:
Add an unstable C API to read a single local variable of an internal interpreter frame by its localsplus index:
PyObject *
PyUnstable_InterpreterFrame_GetLocal(struct _PyInterpreterFrame *frame,
Py_ssize_t index);
Returns a new strong reference, with cell and free variables unboxed to their contents. Free variables are resolved from the function closure, so it also works on a frame that has not started executing (before COPY_FREE_VARS). index outside [0, co_nlocalsplus) returns NULL with an IndexError set; an unset or hidden slot returns NULL with no exception set. The frame is not modified.
Motivation
TorchDynamo (PyTorch JIT compiler) relies on the eval frame API (PEP 523), and one of the things it needs to do when it intercepts a frame is to read the frame's local variables.
CPython has 3 public APIs for reading frame locals, but none of them are suitable to be used in Dynamo:
PyFrame_GetLocals(PyFrameObject*)
PyFrame_GetVar(PyFrameObject*, PyObject*)
PyEval_GetFrameLocals(void)
The first two take a PyFrameObject* as first argument and there's no public way to get one from a _PyInterpreterFrame*. The last one (PyEval_GetFrameLocals) reads the current frame, and the frame might not be ready when Dynamo gets it.
So today PyTorch implements its own version of *_GetLocals, which relies on an interface that is fragile and hard to maintain.
Has this already been discussed elsewhere?
I have already discussed this feature proposal on Discourse
Links to previous discussion of this feature:
https://discuss.python.org/t/add-pyunstable-interpreterframe-getlocals-read-a-frame-s-locals-from-the-interpreter-frame-c-api/108520
Linked PRs
Proposal:
Add an unstable C API to read a single local variable of an internal interpreter frame by its localsplus index:
Returns a new strong reference, with cell and free variables unboxed to their contents. Free variables are resolved from the function closure, so it also works on a frame that has not started executing (before COPY_FREE_VARS). index outside [0, co_nlocalsplus) returns NULL with an IndexError set; an unset or hidden slot returns NULL with no exception set. The frame is not modified.
Motivation
TorchDynamo (PyTorch JIT compiler) relies on the eval frame API (PEP 523), and one of the things it needs to do when it intercepts a frame is to read the frame's local variables.
CPython has 3 public APIs for reading frame locals, but none of them are suitable to be used in Dynamo:
PyFrame_GetLocals(PyFrameObject*)PyFrame_GetVar(PyFrameObject*, PyObject*)PyEval_GetFrameLocals(void)The first two take a
PyFrameObject*as first argument and there's no public way to get one from a_PyInterpreterFrame*. The last one (PyEval_GetFrameLocals) reads the current frame, and the frame might not be ready when Dynamo gets it.So today PyTorch implements its own version of
*_GetLocals, which relies on an interface that is fragile and hard to maintain.Has this already been discussed elsewhere?
I have already discussed this feature proposal on Discourse
Links to previous discussion of this feature:
https://discuss.python.org/t/add-pyunstable-interpreterframe-getlocals-read-a-frame-s-locals-from-the-interpreter-frame-c-api/108520
Linked PRs
PyUnstable_InterpreterFrame_GetLocals#156134