Please add PyObject_CallFinalizer and PyObject_CallFinalizerFromDealloc to the stable ABI.
The documentation for PyObject_CallFinalizer and PyObject_CallFinalizerFromDealloc state:
Call this function (or PyObject_CallFinalizerFromDealloc()) instead of calling tp_finalize directly because this function may deduplicate multiple calls to tp_finalize. Currently, calls are only deduplicated if the type supports garbage collection (i.e., the Py_TPFLAGS_HAVE_GC flag is set); this may change in the future.
These functions are not yet in the stable ABI. I believe it is possible to approximate their current behavior using PyObject_GC_IsFinalized (which is stable ABI) to decide whether to call the finalizer. Given the documentation states that the logic for deduplicating calls may change in future, it seems better to just add the functions to the stable ABI rather than leave downstream users to recreate their logic.
Has this already been discussed elsewhere?
This is a minor feature, which does not need previous discussion elsewhere
Exposing PyObject_CallFinalizerFromDealloc makes sense, but is PyObject_CallFinalizer needed? We have only one internal usage in _PyIOBase_finalize, and I'm not even sure that code path is ever taken.
changed the title [-]Please add `PyObject_CallFinalizer` (& `FromDealloc` variant) to stable ABI[/-][+]Please add `PyObject_CallFinalizerFromDealloc()` to stable ABI[/+]on Mar 20, 2026
Cython has missed this API too. I think I came to the conclusion that I could reimplement PyObject_CallFinalizer (with PyType_GetSlot and a function call, but I couldn't see any way of marking an object as finalized after calling it.
(Edit: Looking at the code, it's actually marked as finalized inside PyObject_CallFinalizer so it wouldn't be possible to reimplement this.... Either way, we have no real need to manually call a finalizer outside of dealloc)
Activity
pythongh-146063: Add PyObject_CallFinalizer() to the limited C API
vstinner commented on Mar 19, 2026
I wrote #146172 to add PyObject_CallFinalizer() and PyObject_CallFinalizerFromDealloc() to the limited C API.
colesbury commented on Mar 19, 2026
Exposing PyObject_CallFinalizerFromDealloc makes sense, but is PyObject_CallFinalizer needed? We have only one internal usage in _PyIOBase_finalize, and I'm not even sure that code path is ever taken.
I don't really see any external usages, except people re-exposing or binding it: https://grep.app/search?regexp=true&q=PyObject_CallFinalizer%5C%28
davidhewitt commented on Mar 19, 2026
I could support having just PyObject_CallFinalizerFromDealloc, that was the indeed the one that we were looking at in PyO3.
da-woods commented on Mar 23, 2026
Cython has missed this API too. I think I came to the conclusion that I could reimplement PyObject_CallFinalizer (with PyType_GetSlot and a function call, but I couldn't see any way of marking an object as finalized after calling it.
(Edit: Looking at the code, it's actually marked as finalized inside PyObject_CallFinalizer so it wouldn't be possible to reimplement this.... Either way, we have no real need to manually call a finalizer outside of dealloc)
Here's a previous discussion that didn't get a whole lot of interest: https://discuss.python.org/t/fully-support-using-the-tp-finalize-slot-of-a-pyobject-in-the-limited-api/69729
encukou commented on Apr 14, 2026
C API WG vote: capi-workgroup/decisions#104
gh-146063: Add PyObject_CallFinalizerFromDealloc() to the limited C A…
vstinner commented on May 13, 2026
PyObject_CallFinalizerFromDealloc() has been added to Python 3.15: https://docs.python.org/dev/c-api/lifecycle.html#c.PyObject_CallFinalizerFromDealloc. The function was added to the stable ABI as well.
davidhewitt commented on May 13, 2026
Many thanks!