On 25.02.2022 13:15, Victor Stinner wrote:
Hi,
tl; dr the C API of PyFrameObject changed. If you have issues, please speak up!
I moved the PyFrameObject structure to the internal C API headers. You should now use the public C API to access its members:
f_back
: use :c:func:PyFrame_GetBack
.
You only mention C APIs, but inspection tools are often written in Python. How can they access and walk the frames on the stack ?
Are these members still available as Python attributes of the frame objects ?
f_blockstack
: removed.f_builtins
: usePyObject_GetAttrString((PyObject*)frame, "f_builtins")
.f_code
: use :c:func:PyFrame_GetCode
.f_gen
: removed.f_globals
: usePyObject_GetAttrString((PyObject*)frame, "f_globals")
.f_iblock
: removed.f_lasti
: usePyObject_GetAttrString((PyObject*)frame, "f_lasti")
. Code usingf_lasti
withPyCode_Addr2Line()
must use :c:func:PyFrame_GetLineNumber
instead.f_lineno
: use :c:func:PyFrame_GetLineNumber
f_locals
: usePyObject_GetAttrString((PyObject*)frame, "f_locals")
.f_stackdepth
: removed.f_state
: no public API (renamed tof_frame.f_state
).f_trace
: no public API.f_trace_lines
: usePyObject_GetAttrString((PyObject*)frame, "f_trace_lines")
(it also be modified).f_trace_opcodes
: usePyObject_GetAttrString((PyObject*)frame, "f_trace_opcodes")
(it also be modified).f_localsplus
: no public API (renamed tof_frame.localsplus
).f_valuestack
: removed.See What's New in Python 3.11 for more details (I completed the doc, but it will only be updated online tomorrow, there is a cron task once per day): https://docs.python.org/dev/whatsnew/3.11.html#id2
You can use the pythoncapi_compat project to get PyFrame_GetBack() and PyFrame_GetCode() on Python 3.8 and older: https://pythoncapi-compat.readthedocs.io/
If there is no public C API to access the PyFrameObject members used by your project, please speak up!
See for example my PR to use the public C API in coverage: https://github.com/nedbat/coveragepy/pull/1331
There is an on-going work for 2 years to add new getter functions for PyFrameObject: https://bugs.python.org/issue40421
In Python 3.10, there was no rush to make the structure internal. Things changed quickly in Python 3.11: a heavy rework on Python internals is on-going to optimize Python (especially ceval.c and how frames are created and used). For example, the _PyEval_EvalFrameDefault() function now gets a new InterpreterFrame structure, it no longer takes a PyFrameObject. Python 3.11 now creates Python frame objects on demand.
Because of these changes, reading directly PyFrameObject.f_back is now an error since the member is not always filled, but it wasn't a compiler error. You must now call the public PyFrame_GetBack() function rather than accessing directly to the member.
Since Python 2.3 (that's quite old ;-)), reading directly PyFrameObject.f_lineno is unsafe since it depends if the Python code is being traced or not: you must use PyFrame_GetLineNumber() instead.
See also the issue for the longer rationale: https://bugs.python.org/issue46836
I know that these changes are inconvenient, but I'm here if you need my help for updating your project! Moreover, Python 3.11 is scheduled for October, so there are still a few months to adapt your project, and maybe add new getter functions. The best would be to add all required getter functions before Python 3.11 beta1 scheduled for the beginning of May (2022-05-06).
Victor
-- Marc-Andre Lemburg eGenix.com
Professional Python Services directly from the Experts (#1, Feb 25 2022)
Python Projects, Coaching and Support ... https://www.egenix.com/ Python Product Development ... https://consulting.egenix.com/
::: We implement business ideas - efficiently in both time and costs :::
eGenix.com Software, Skills and Services GmbH Pastor-Loeh-Str.48 D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg Registered at Amtsgericht Duesseldorf: HRB 46611 https://www.egenix.com/company/contact/ https://www.malemburg.com/