Yes, the f_state
field has been removed.
For 3.11, you can use the owner
field defined in cpython/pycore_frame.h at main · python/cpython · GitHub, it won’t change before 3.12.
We should have a better API for 3.12
Yes, the f_state
field has been removed.
For 3.11, you can use the owner
field defined in cpython/pycore_frame.h at main · python/cpython · GitHub, it won’t change before 3.12.
We should have a better API for 3.12
Hey there again,
I was working on the support of 3.11
for the Blackfire profiler and faced an issue that I had previously mentioned above:
If the function is built-in(C function) we read it from
frame->f_valuestack
and if the function is a normal Python function we use:arg_name = PyTuple_GetItem(frame->f_code->co_varnames, int_arg_id-1);
I use f_valuestack
to retrieve some arguments from the C functions(PyCFunction
) inside the profiler. This field seems to be removed in 3.11
without a corresponding API.
So, the question for me is: Is there any other way to read PyCFunction
call stack in the runtime? Again: this is used this for retrieving arguments of built-in functions before:
arg_id = 0 // positional index for the argument
arg_val = frame->f_valuestack[arg_id];
I have a pending PR to add PyFrame_GetVar(), would it fit your usecase? Can you call functions?gh-91248: Add PyFrame_GetVar() function by vstinner · Pull Request #95712 · python/cpython · GitHub
IIUC, this API will not solve the problem I described above, but it solves another one. Getting variables from frame->locals was always a hassle. I was using the following code to get the locals and then using another one to get the variables. And cell variables were always a problem, too.
static PyObject *_get_locals(PyFrameObject *fobj) {
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 10
return PyEval_GetLocals();
#else
PyObject *locals;
PyFrame_FastToLocals(fobj);
locals = fobj->f_locals;
PyFrame_LocalsToFast(fobj, 0);
return locals;
#endif
}
Now coming to the original problem: the problem for me is I need to read locals of a C function.
Example: if user calls time.sleep(1.0)
, I need to get 1.0
. We have a special configuration file where we set: fn_name: "time.sleep", arg_id: 0
. From this, I was getting the C function’s argument by reading from frame->f_valuestack
. Now, I am not sure how to accomplish this with PyFrame_GetVar
?