GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — [C API] Promote PEP 523 functions to public functions: add `PyUnstable_InterpreterState_SetEvalFrameFunc()` · Issue #141518 · python/cpython

[C API] Promote PEP 523 functions to public functions: add PyUnstable_InterpreterState_SetEvalFrameFunc() #141518

New issue
Copy link
New issue
Copy link
Closed
Closed
[C API] Promote PEP 523 functions to public functions: add PyUnstable_InterpreterState_SetEvalFrameFunc()#141518
Copy link
Labels
interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)topic-C-APItype-featureA feature request or enhancementA feature request or enhancement

Description

@vstinner
vstinner
opened on Nov 13, 2025
Issue body actions

C extensions should not use private functions (functions prefixed by _Py), but PEP 523 only added private functions:

  • _PyInterpreterState_GetEvalFrameFunc()
  • _PyInterpreterState_SetEvalFrameFunc()
  • _PyEval_EvalFrameDefault()

I propose promoting these functions as public functions (just remove the _ prefix):

  • PyUnstable_InterpreterState_GetEvalFrameFunc()
  • PyUnstable_InterpreterState_SetEvalFrameFunc()
  • PyUnstable_Eval_EvalFrameDefault()

cc @emmatyping

Update: I added PyUnstable_ prefix to function names.

Linked PRs

  • gh-141518: Add PyUnstable_InterpreterState_SetEvalFrameFunc() #141665
  • gh-141518: Add PyUnstable_InterpreterFrame_GetFrameObject() function #141950

Activity

  1. vstinner
    added
    topic-C-API
    on Nov 13, 2025
  2. vstinner commented on Nov 13, 2025

    @vstinner
    vstinner
    on Nov 13, 2025
    MemberAuthor
    More actions

    A code search on PyPI top 15,000 projects using regex _PyInterpreterState_GetEvalFrameFunc|_PyInterpreterState_SetEvalFrameFunc|_PyEval_EvalFrameDefault didn't find _PyInterpreterState_GetEvalFrameFunc() or _PyInterpreterState_SetEvalFrameFunc() usage, but found _PyEval_EvalFrameDefault() usage in 7 projects:

    • cython (3.1.4)
    • debugpy (1.8.17)
    • memray (1.18.0)
    • numpy (2.3.3)
    • ptvsd (4.3.2)
    • pystack (1.5.1)
    • river (0.22.0)
    Details
    cython-3.1.4.tar.gz: cython-3.1.4/Cython/Debugger/libpython.py: EVALFRAME = '_PyEval_EvalFrameDefault'
    debugpy-1.8.17.tar.gz: debugpy-1.8.17/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pxd: #define CALL_EvalFrameDefault_39(a, b, c)    _PyEval_EvalFrameDefault(a, b, c)
    debugpy-1.8.17.tar.gz: debugpy-1.8.17/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pxd: #define CALL_EvalFrameDefault_38(a, b)    _PyEval_EvalFrameDefault(a, b)
    debugpy-1.8.17.tar.gz: debugpy-1.8.17/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pxd: PyObject* _PyEval_EvalFrameDefault(...)
    debugpy-1.8.17.tar.gz: debugpy-1.8.17/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pyx: state.interp.eval_frame = _PyEval_EvalFrameDefault
    debugpy-1.8.17.tar.gz: debugpy-1.8.17/src/debugpy/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.template.pyx: state.interp.eval_frame = _PyEval_EvalFrameDefault
    memray-1.18.0.tar.gz: memray-1.18.0/src/memray/_memray.pyx: if pidx >= 0 and "_PyEval_EvalFrameDefault" in symbol:
    memray-1.18.0.tar.gz: memray-1.18.0/src/memray/_memray.pyx: if function != "_PyEval_EvalFrameDefault":
    memray-1.18.0.tar.gz: memray-1.18.0/src/memray/reporters/frame_tools.py: if "PyEval_EvalFrameEx" in symbol or "_PyEval_EvalFrameDefault" in symbol:
    numpy-2.3.3.tar.gz: numpy-2.3.3/numpy/_core/src/multiarray/temp_elide.c: #define PYFRAMEEVAL_FUNC "_PyEval_EvalFrameDefault"
    ptvsd-4.3.2.zip: ptvsd-4.3.2/src/ptvsd/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pxd: PyObject* _PyEval_EvalFrameDefault(PyFrameObject *frame, int exc)
    ptvsd-4.3.2.zip: ptvsd-4.3.2/src/ptvsd/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pyx: return _PyEval_EvalFrameDefault(frame_obj, exc)
    ptvsd-4.3.2.zip: ptvsd-4.3.2/src/ptvsd/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pyx: return _PyEval_EvalFrameDefault(frame_obj, exc)
    ptvsd-4.3.2.zip: ptvsd-4.3.2/src/ptvsd/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pyx: return _PyEval_EvalFrameDefault(frame_obj, exc)
    ptvsd-4.3.2.zip: ptvsd-4.3.2/src/ptvsd/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pyx: return _PyEval_EvalFrameDefault(frame_obj, exc)
    ptvsd-4.3.2.zip: ptvsd-4.3.2/src/ptvsd/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pyx: return _PyEval_EvalFrameDefault(frame_obj, exc)
    ptvsd-4.3.2.zip: ptvsd-4.3.2/src/ptvsd/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pyx: return _PyEval_EvalFrameDefault(frame_obj, exc)
    ptvsd-4.3.2.zip: ptvsd-4.3.2/src/ptvsd/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pyx: return _PyEval_EvalFrameDefault(frame_obj, exc)
    ptvsd-4.3.2.zip: ptvsd-4.3.2/src/ptvsd/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pyx: state.interp.eval_frame = _PyEval_EvalFrameDefault
    pystack-1.5.1.tar.gz: pystack-1.5.1/src/pystack/types.py: return "_PyEval_EvalFrameDefault" in symbol
    river-0.22.0.tar.gz: river-0.22.0/.venv/lib/python3.13/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pxd: #define CALL_EvalFrameDefault_39(a, b, c)    _PyEval_EvalFrameDefault(a, b, c)
    river-0.22.0.tar.gz: river-0.22.0/.venv/lib/python3.13/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pxd: #define CALL_EvalFrameDefault_38(a, b)    _PyEval_EvalFrameDefault(a, b)
    river-0.22.0.tar.gz: river-0.22.0/.venv/lib/python3.13/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.pxd: PyObject* _PyEval_EvalFrameDefault(...)
    river-0.22.0.tar.gz: river-0.22.0/.venv/lib/python3.13/site-packages/debugpy/_vendored/pydevd/_pydevd_frame_eval/pydevd_frame_evaluator.template.pyx: state.interp.eval_frame = _PyEval_EvalFrameDefault
    
  3. vstinner commented on Nov 13, 2025

    @vstinner
    vstinner
    on Nov 13, 2025
    MemberAuthor
    More actions

    PyCharm blog post from 2017 about PEP 523 APIs: https://blog.jetbrains.com/pycharm/2017/03/inside-the-debugger-interview-with-elizaveta-shashkova/

    What changed in Python 3.6 to allow this?
    The new frame evaluation API was introduced to CPython in PEP 523 and it allows to specify a per-interpreter function pointer to handle the evaluation of frames.

  4. vstinner commented on Nov 13, 2025

    @vstinner
    vstinner
    on Nov 13, 2025
    MemberAuthor
    More actions

    PyTorch Dynamo says that it uses the PEP 523 API: https://docs.pytorch.org/docs/stable/torch.compiler_dynamo_overview.html

    Dynamo hooks into the frame evaluation API in CPython (PEP 523) to dynamically modify Python bytecode right before it is executed.

  5. StanFromIreland
    added
    type-featureA feature request or enhancementA feature request or enhancement
    interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)
    on Nov 13, 2025
  6. emmatyping commented on Nov 13, 2025

    @emmatyping
    emmatyping
    on Nov 13, 2025
    Member
    More actions

    Perhaps it would be better to make these PyUnstable functions? I believe there was discussion at PyCon this year (and it seems in the past) about issues with the frame evaluation C API. Looping in a few people who probably have stronger opinions than I:
    @markshannon
    @jansel
    @itamaro

    Reacted by Petr Viktorin
  7. jansel commented on Nov 13, 2025

    @jansel
    jansel
    on Nov 13, 2025
    More actions

    PyTorch's torch.compile uses PEP 523. PyUnstable would be fine for us. We already need to do extra work to support each new Python version primarily due to Python bytecode changes.

  8. itamaro commented on Nov 14, 2025

    @itamaro
    itamaro
    on Nov 14, 2025
    Contributor
    More actions

    As long as the frame evaluation API provides the functionality along PEP 523 spirit, I don't think it matters to us (cinder jit in this context) what's the exact spelling. Right @DinoV ?

  9. markshannon commented on Nov 14, 2025

    @markshannon
    markshannon
    on Nov 14, 2025
    Member
    More actions

    A code search on PyPI top 15,000 projects using regex...

    Those are either:

    • a vendored old version of pydevd. All debuggers now use sys.monitoring
    • pystack/memray -- They both probe into CPython internals, so don't much care about APIs.

    The only use case that matters, and probably the only use case at all, is PyTorch.

    I don't want to make the API public because that entails a lot of defining semantics and guarantees about future compatibility. It also effectively makes the interpreter frame part of the public API, and I don't want that either.

    Making them PyUnstable seems best.

    Reacted by Emma Smith and Mikhail Efimov
  10. vstinner
    changed the title [-][C API] Promote PEP 523 functions to public functions: add `PyInterpreterState_SetEvalFrameFunc()`[/-] [+][C API] Promote PEP 523 functions to public functions: add `PyUnstable_InterpreterState_SetEvalFrameFunc()`[/+] on Nov 14, 2025
  11. DinoV commented on Nov 16, 2025

    @DinoV
    DinoV
    on Nov 16, 2025
    Contributor
    More actions

    As long as the frame evaluation API provides the functionality along PEP 523 spirit, I don't think it matters to us (cinder jit in this context) what's the exact spelling. Right @DinoV ?

    Correct, a rename is no big deal, I think this probably just predated the PyUnstable convention.

    Reacted by Emma Smith, Mikhail Efimov and Victor Stinner
  12. vstinner
    added 2 commits that reference this issue on Nov 17, 2025

    pythongh-141518: Add PyUnstable_InterpreterState_SetEvalFrameFunc()

    de37eba

    pythongh-141518: Add PyUnstable_InterpreterState_SetEvalFrameFunc()

    0e322e4
  13. vstinner commented on Nov 17, 2025

    @vstinner
    vstinner
    on Nov 17, 2025
    MemberAuthor
    More actions

    I created #141665 to add PyUnstable_InterpreterState_SetEvalFrameFunc() function.

  14. vstinner
    added a commit that references this issue on Nov 25, 2025

    pythongh-141518: Add PyUnstable_InterpreterFrame_GetFrameObject() fun…

    58ac314
  15. vstinner commented on Feb 10, 2026

    @vstinner
    vstinner
    on Feb 10, 2026
    MemberAuthor
    More actions

    The C API Working Group decided to not add a public function for this feature, but keep the _Py name instead: capi-workgroup/decisions#89.

  16. vstinner
    closed this as completedon Feb 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)topic-C-APItype-featureA feature request or enhancementA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.