mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
[3.14] gh-75459: Doc: C API: Improve object life cycle documentation (GH-125962) (GH-134344)
gh-75459: Doc: C API: Improve object life cycle documentation (GH-125962)
* Add "cyclic isolate" to the glossary.
* Add a new "Object Life Cycle" page.
* Improve docs for related API, with special focus on cross-references and warnings
(cherry picked from commit 3246ea514d)
Co-authored-by: Richard Hansen <rhansen@rhansen.org>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
This commit is contained in:
parent
6d4b56d2f3
commit
6074e1e6c4
13 changed files with 1384 additions and 135 deletions
|
|
@ -676,77 +676,122 @@ and :c:data:`PyType_Type` effectively act as defaults.)
|
|||
|
||||
.. c:member:: destructor PyTypeObject.tp_dealloc
|
||||
|
||||
A pointer to the instance destructor function. This function must be defined
|
||||
unless the type guarantees that its instances will never be deallocated (as is
|
||||
the case for the singletons ``None`` and ``Ellipsis``). The function signature is::
|
||||
A pointer to the instance destructor function. The function signature is::
|
||||
|
||||
void tp_dealloc(PyObject *self);
|
||||
|
||||
The destructor function is called by the :c:func:`Py_DECREF` and
|
||||
:c:func:`Py_XDECREF` macros when the new reference count is zero. At this point,
|
||||
the instance is still in existence, but there are no references to it. The
|
||||
destructor function should free all references which the instance owns, free all
|
||||
memory buffers owned by the instance (using the freeing function corresponding
|
||||
to the allocation function used to allocate the buffer), and call the type's
|
||||
:c:member:`~PyTypeObject.tp_free` function. If the type is not subtypable
|
||||
(doesn't have the :c:macro:`Py_TPFLAGS_BASETYPE` flag bit set), it is
|
||||
permissible to call the object deallocator directly instead of via
|
||||
:c:member:`~PyTypeObject.tp_free`. The object deallocator should be the one used to allocate the
|
||||
instance; this is normally :c:func:`PyObject_Free` if the instance was allocated
|
||||
using :c:macro:`PyObject_New` or :c:macro:`PyObject_NewVar`, or
|
||||
:c:func:`PyObject_GC_Del` if the instance was allocated using
|
||||
:c:macro:`PyObject_GC_New` or :c:macro:`PyObject_GC_NewVar`.
|
||||
The destructor function should remove all references which the instance owns
|
||||
(e.g., call :c:func:`Py_CLEAR`), free all memory buffers owned by the
|
||||
instance, and call the type's :c:member:`~PyTypeObject.tp_free` function to
|
||||
free the object itself.
|
||||
|
||||
If the type supports garbage collection (has the :c:macro:`Py_TPFLAGS_HAVE_GC`
|
||||
flag bit set), the destructor should call :c:func:`PyObject_GC_UnTrack`
|
||||
No guarantees are made about when an object is destroyed, except:
|
||||
|
||||
* Python will destroy an object immediately or some time after the final
|
||||
reference to the object is deleted, unless its finalizer
|
||||
(:c:member:`~PyTypeObject.tp_finalize`) subsequently resurrects the
|
||||
object.
|
||||
* An object will not be destroyed while it is being automatically finalized
|
||||
(:c:member:`~PyTypeObject.tp_finalize`) or automatically cleared
|
||||
(:c:member:`~PyTypeObject.tp_clear`).
|
||||
|
||||
CPython currently destroys an object immediately from :c:func:`Py_DECREF`
|
||||
when the new reference count is zero, but this may change in a future
|
||||
version.
|
||||
|
||||
It is recommended to call :c:func:`PyObject_CallFinalizerFromDealloc` at the
|
||||
beginning of :c:member:`!tp_dealloc` to guarantee that the object is always
|
||||
finalized before destruction.
|
||||
|
||||
If the type supports garbage collection (the :c:macro:`Py_TPFLAGS_HAVE_GC`
|
||||
flag is set), the destructor should call :c:func:`PyObject_GC_UnTrack`
|
||||
before clearing any member fields.
|
||||
|
||||
.. code-block:: c
|
||||
It is permissible to call :c:member:`~PyTypeObject.tp_clear` from
|
||||
:c:member:`!tp_dealloc` to reduce code duplication and to guarantee that the
|
||||
object is always cleared before destruction. Beware that
|
||||
:c:member:`!tp_clear` might have already been called.
|
||||
|
||||
static void
|
||||
foo_dealloc(PyObject *op)
|
||||
{
|
||||
If the type is heap allocated (:c:macro:`Py_TPFLAGS_HEAPTYPE`), the
|
||||
deallocator should release the owned reference to its type object (via
|
||||
:c:func:`Py_DECREF`) after calling the type deallocator. See the example
|
||||
code below.::
|
||||
|
||||
static void
|
||||
foo_dealloc(PyObject *op)
|
||||
{
|
||||
foo_object *self = (foo_object *) op;
|
||||
PyObject_GC_UnTrack(self);
|
||||
Py_CLEAR(self->ref);
|
||||
Py_TYPE(self)->tp_free(self);
|
||||
}
|
||||
}
|
||||
|
||||
Finally, if the type is heap allocated (:c:macro:`Py_TPFLAGS_HEAPTYPE`), the
|
||||
deallocator should release the owned reference to its type object
|
||||
(via :c:func:`Py_DECREF`) after
|
||||
calling the type deallocator. In order to avoid dangling pointers, the
|
||||
recommended way to achieve this is:
|
||||
:c:member:`!tp_dealloc` must leave the exception status unchanged. If it
|
||||
needs to call something that might raise an exception, the exception state
|
||||
must be backed up first and restored later (after logging any exceptions
|
||||
with :c:func:`PyErr_WriteUnraisable`).
|
||||
|
||||
.. code-block:: c
|
||||
Example::
|
||||
|
||||
static void
|
||||
foo_dealloc(PyObject *op)
|
||||
{
|
||||
PyTypeObject *tp = Py_TYPE(op);
|
||||
// free references and buffers here
|
||||
tp->tp_free(op);
|
||||
Py_DECREF(tp);
|
||||
}
|
||||
static void
|
||||
foo_dealloc(PyObject *self)
|
||||
{
|
||||
PyObject *exc = PyErr_GetRaisedException();
|
||||
|
||||
.. warning::
|
||||
if (PyObject_CallFinalizerFromDealloc(self) < 0) {
|
||||
// self was resurrected.
|
||||
goto done;
|
||||
}
|
||||
|
||||
In a garbage collected Python, :c:member:`!tp_dealloc` may be called from
|
||||
any Python thread, not just the thread which created the object (if the
|
||||
object becomes part of a refcount cycle, that cycle might be collected by
|
||||
a garbage collection on any thread). This is not a problem for Python
|
||||
API calls, since the thread on which :c:member:`!tp_dealloc` is called
|
||||
with an :term:`attached thread state`. However, if the object being
|
||||
destroyed in turn destroys objects from some other C or C++ library, care
|
||||
should be taken to ensure that destroying those objects on the thread
|
||||
which called :c:member:`!tp_dealloc` will not violate any assumptions of
|
||||
the library.
|
||||
PyTypeObject *tp = Py_TYPE(self);
|
||||
|
||||
if (tp->tp_flags & Py_TPFLAGS_HAVE_GC) {
|
||||
PyObject_GC_UnTrack(self);
|
||||
}
|
||||
|
||||
// Optional, but convenient to avoid code duplication.
|
||||
if (tp->tp_clear && tp->tp_clear(self) < 0) {
|
||||
PyErr_WriteUnraisable(self);
|
||||
}
|
||||
|
||||
// Any additional destruction goes here.
|
||||
|
||||
tp->tp_free(self);
|
||||
self = NULL; // In case PyErr_WriteUnraisable() is called below.
|
||||
|
||||
if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE) {
|
||||
Py_CLEAR(tp);
|
||||
}
|
||||
|
||||
done:
|
||||
// Optional, if something was called that might have raised an
|
||||
// exception.
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_WriteUnraisable(self);
|
||||
}
|
||||
PyErr_SetRaisedException(exc);
|
||||
}
|
||||
|
||||
:c:member:`!tp_dealloc` may be called from
|
||||
any Python thread, not just the thread which created the object (if the
|
||||
object becomes part of a refcount cycle, that cycle might be collected by
|
||||
a garbage collection on any thread). This is not a problem for Python
|
||||
API calls, since the thread on which :c:member:`!tp_dealloc` is called
|
||||
with an :term:`attached thread state`. However, if the object being
|
||||
destroyed in turn destroys objects from some other C library, care
|
||||
should be taken to ensure that destroying those objects on the thread
|
||||
which called :c:member:`!tp_dealloc` will not violate any assumptions of
|
||||
the library.
|
||||
|
||||
|
||||
**Inheritance:**
|
||||
|
||||
This field is inherited by subtypes.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`life-cycle` for details about how this slot relates to other slots.
|
||||
|
||||
|
||||
.. c:member:: Py_ssize_t PyTypeObject.tp_vectorcall_offset
|
||||
|
||||
|
|
@ -1137,11 +1182,11 @@ and :c:data:`PyType_Type` effectively act as defaults.)
|
|||
.. c:macro:: Py_TPFLAGS_HAVE_GC
|
||||
|
||||
This bit is set when the object supports garbage collection. If this bit
|
||||
is set, instances must be created using :c:macro:`PyObject_GC_New` and
|
||||
destroyed using :c:func:`PyObject_GC_Del`. More information in section
|
||||
:ref:`supporting-cycle-detection`. This bit also implies that the
|
||||
GC-related fields :c:member:`~PyTypeObject.tp_traverse` and :c:member:`~PyTypeObject.tp_clear` are present in
|
||||
the type object.
|
||||
is set, memory for new instances (see :c:member:`~PyTypeObject.tp_alloc`)
|
||||
must be allocated using :c:macro:`PyObject_GC_New` or
|
||||
:c:func:`PyType_GenericAlloc` and deallocated (see
|
||||
:c:member:`~PyTypeObject.tp_free`) using :c:func:`PyObject_GC_Del`. More
|
||||
information in section :ref:`supporting-cycle-detection`.
|
||||
|
||||
**Inheritance:**
|
||||
|
||||
|
|
@ -1478,6 +1523,11 @@ and :c:data:`PyType_Type` effectively act as defaults.)
|
|||
heap-allocated superclass).
|
||||
If they do not, the type object may not be garbage-collected.
|
||||
|
||||
.. note::
|
||||
|
||||
The :c:member:`~PyTypeObject.tp_traverse` function can be called from any
|
||||
thread.
|
||||
|
||||
.. versionchanged:: 3.9
|
||||
|
||||
Heap-allocated types are expected to visit ``Py_TYPE(self)`` in
|
||||
|
|
@ -1497,20 +1547,101 @@ and :c:data:`PyType_Type` effectively act as defaults.)
|
|||
|
||||
.. c:member:: inquiry PyTypeObject.tp_clear
|
||||
|
||||
An optional pointer to a clear function for the garbage collector. This is only
|
||||
used if the :c:macro:`Py_TPFLAGS_HAVE_GC` flag bit is set. The signature is::
|
||||
An optional pointer to a clear function. The signature is::
|
||||
|
||||
int tp_clear(PyObject *);
|
||||
|
||||
The :c:member:`~PyTypeObject.tp_clear` member function is used to break reference cycles in cyclic
|
||||
garbage detected by the garbage collector. Taken together, all :c:member:`~PyTypeObject.tp_clear`
|
||||
functions in the system must combine to break all reference cycles. This is
|
||||
subtle, and if in any doubt supply a :c:member:`~PyTypeObject.tp_clear` function. For example,
|
||||
the tuple type does not implement a :c:member:`~PyTypeObject.tp_clear` function, because it's
|
||||
possible to prove that no reference cycle can be composed entirely of tuples.
|
||||
Therefore the :c:member:`~PyTypeObject.tp_clear` functions of other types must be sufficient to
|
||||
break any cycle containing a tuple. This isn't immediately obvious, and there's
|
||||
rarely a good reason to avoid implementing :c:member:`~PyTypeObject.tp_clear`.
|
||||
The purpose of this function is to break reference cycles that are causing a
|
||||
:term:`cyclic isolate` so that the objects can be safely destroyed. A
|
||||
cleared object is a partially destroyed object; the object is not obligated
|
||||
to satisfy design invariants held during normal use.
|
||||
|
||||
:c:member:`!tp_clear` does not need to delete references to objects that
|
||||
can't participate in reference cycles, such as Python strings or Python
|
||||
integers. However, it may be convenient to clear all references, and write
|
||||
the type's :c:member:`~PyTypeObject.tp_dealloc` function to invoke
|
||||
:c:member:`!tp_clear` to avoid code duplication. (Beware that
|
||||
:c:member:`!tp_clear` might have already been called. Prefer calling
|
||||
idempotent functions like :c:func:`Py_CLEAR`.)
|
||||
|
||||
Any non-trivial cleanup should be performed in
|
||||
:c:member:`~PyTypeObject.tp_finalize` instead of :c:member:`!tp_clear`.
|
||||
|
||||
.. note::
|
||||
|
||||
If :c:member:`!tp_clear` fails to break a reference cycle then the
|
||||
objects in the :term:`cyclic isolate` may remain indefinitely
|
||||
uncollectable ("leak"). See :data:`gc.garbage`.
|
||||
|
||||
.. note::
|
||||
|
||||
Referents (direct and indirect) might have already been cleared; they are
|
||||
not guaranteed to be in a consistent state.
|
||||
|
||||
.. note::
|
||||
|
||||
The :c:member:`~PyTypeObject.tp_clear` function can be called from any
|
||||
thread.
|
||||
|
||||
.. note::
|
||||
|
||||
An object is not guaranteed to be automatically cleared before its
|
||||
destructor (:c:member:`~PyTypeObject.tp_dealloc`) is called.
|
||||
|
||||
This function differs from the destructor
|
||||
(:c:member:`~PyTypeObject.tp_dealloc`) in the following ways:
|
||||
|
||||
* The purpose of clearing an object is to remove references to other objects
|
||||
that might participate in a reference cycle. The purpose of the
|
||||
destructor, on the other hand, is a superset: it must release *all*
|
||||
resources it owns, including references to objects that cannot participate
|
||||
in a reference cycle (e.g., integers) as well as the object's own memory
|
||||
(by calling :c:member:`~PyTypeObject.tp_free`).
|
||||
* When :c:member:`!tp_clear` is called, other objects might still hold
|
||||
references to the object being cleared. Because of this,
|
||||
:c:member:`!tp_clear` must not deallocate the object's own memory
|
||||
(:c:member:`~PyTypeObject.tp_free`). The destructor, on the other hand,
|
||||
is only called when no (strong) references exist, and as such, must
|
||||
safely destroy the object itself by deallocating it.
|
||||
* :c:member:`!tp_clear` might never be automatically called. An object's
|
||||
destructor, on the other hand, will be automatically called some time
|
||||
after the object becomes unreachable (i.e., either there are no references
|
||||
to the object or the object is a member of a :term:`cyclic isolate`).
|
||||
|
||||
No guarantees are made about when, if, or how often Python automatically
|
||||
clears an object, except:
|
||||
|
||||
* Python will not automatically clear an object if it is reachable, i.e.,
|
||||
there is a reference to it and it is not a member of a :term:`cyclic
|
||||
isolate`.
|
||||
* Python will not automatically clear an object if it has not been
|
||||
automatically finalized (see :c:member:`~PyTypeObject.tp_finalize`). (If
|
||||
the finalizer resurrected the object, the object may or may not be
|
||||
automatically finalized again before it is cleared.)
|
||||
* If an object is a member of a :term:`cyclic isolate`, Python will not
|
||||
automatically clear it if any member of the cyclic isolate has not yet
|
||||
been automatically finalized (:c:member:`~PyTypeObject.tp_finalize`).
|
||||
* Python will not destroy an object until after any automatic calls to its
|
||||
:c:member:`!tp_clear` function have returned. This ensures that the act
|
||||
of breaking a reference cycle does not invalidate the ``self`` pointer
|
||||
while :c:member:`!tp_clear` is still executing.
|
||||
* Python will not automatically call :c:member:`!tp_clear` multiple times
|
||||
concurrently.
|
||||
|
||||
CPython currently only automatically clears objects as needed to break
|
||||
reference cycles in a :term:`cyclic isolate`, but future versions might
|
||||
clear objects regularly before their destruction.
|
||||
|
||||
Taken together, all :c:member:`~PyTypeObject.tp_clear` functions in the
|
||||
system must combine to break all reference cycles. This is subtle, and if
|
||||
in any doubt supply a :c:member:`~PyTypeObject.tp_clear` function. For
|
||||
example, the tuple type does not implement a
|
||||
:c:member:`~PyTypeObject.tp_clear` function, because it's possible to prove
|
||||
that no reference cycle can be composed entirely of tuples. Therefore the
|
||||
:c:member:`~PyTypeObject.tp_clear` functions of other types are responsible
|
||||
for breaking any cycle containing a tuple. This isn't immediately obvious,
|
||||
and there's rarely a good reason to avoid implementing
|
||||
:c:member:`~PyTypeObject.tp_clear`.
|
||||
|
||||
Implementations of :c:member:`~PyTypeObject.tp_clear` should drop the instance's references to
|
||||
those of its members that may be Python objects, and set its pointers to those
|
||||
|
|
@ -1545,18 +1676,6 @@ and :c:data:`PyType_Type` effectively act as defaults.)
|
|||
|
||||
PyObject_ClearManagedDict((PyObject*)self);
|
||||
|
||||
Note that :c:member:`~PyTypeObject.tp_clear` is not *always* called
|
||||
before an instance is deallocated. For example, when reference counting
|
||||
is enough to determine that an object is no longer used, the cyclic garbage
|
||||
collector is not involved and :c:member:`~PyTypeObject.tp_dealloc` is
|
||||
called directly.
|
||||
|
||||
Because the goal of :c:member:`~PyTypeObject.tp_clear` functions is to break reference cycles,
|
||||
it's not necessary to clear contained objects like Python strings or Python
|
||||
integers, which can't participate in reference cycles. On the other hand, it may
|
||||
be convenient to clear all contained Python objects, and write the type's
|
||||
:c:member:`~PyTypeObject.tp_dealloc` function to invoke :c:member:`~PyTypeObject.tp_clear`.
|
||||
|
||||
More information about Python's garbage collection scheme can be found in
|
||||
section :ref:`supporting-cycle-detection`.
|
||||
|
||||
|
|
@ -1569,6 +1688,10 @@ and :c:data:`PyType_Type` effectively act as defaults.)
|
|||
:c:member:`~PyTypeObject.tp_clear` are all inherited from the base type if they are all zero in
|
||||
the subtype.
|
||||
|
||||
.. seealso::
|
||||
|
||||
:ref:`life-cycle` for details about how this slot relates to other slots.
|
||||
|
||||
|
||||
.. c:member:: richcmpfunc PyTypeObject.tp_richcompare
|
||||
|
||||
|
|
@ -1945,18 +2068,17 @@ and :c:data:`PyType_Type` effectively act as defaults.)
|
|||
|
||||
**Inheritance:**
|
||||
|
||||
This field is inherited by static subtypes, but not by dynamic
|
||||
subtypes (subtypes created by a class statement).
|
||||
Static subtypes inherit this slot, which will be
|
||||
:c:func:`PyType_GenericAlloc` if inherited from :class:`object`.
|
||||
|
||||
:ref:`Heap subtypes <heap-types>` do not inherit this slot.
|
||||
|
||||
**Default:**
|
||||
|
||||
For dynamic subtypes, this field is always set to
|
||||
:c:func:`PyType_GenericAlloc`, to force a standard heap
|
||||
allocation strategy.
|
||||
For heap subtypes, this field is always set to
|
||||
:c:func:`PyType_GenericAlloc`.
|
||||
|
||||
For static subtypes, :c:data:`PyBaseObject_Type` uses
|
||||
:c:func:`PyType_GenericAlloc`. That is the recommended value
|
||||
for all statically defined types.
|
||||
For static subtypes, this slot is inherited (see above).
|
||||
|
||||
|
||||
.. c:member:: newfunc PyTypeObject.tp_new
|
||||
|
|
@ -2004,20 +2126,27 @@ and :c:data:`PyType_Type` effectively act as defaults.)
|
|||
|
||||
void tp_free(void *self);
|
||||
|
||||
An initializer that is compatible with this signature is :c:func:`PyObject_Free`.
|
||||
This function must free the memory allocated by
|
||||
:c:member:`~PyTypeObject.tp_alloc`.
|
||||
|
||||
**Inheritance:**
|
||||
|
||||
This field is inherited by static subtypes, but not by dynamic
|
||||
subtypes (subtypes created by a class statement)
|
||||
Static subtypes inherit this slot, which will be :c:func:`PyObject_Free` if
|
||||
inherited from :class:`object`. Exception: If the type supports garbage
|
||||
collection (i.e., the :c:macro:`Py_TPFLAGS_HAVE_GC` flag is set in
|
||||
:c:member:`~PyTypeObject.tp_flags`) and it would inherit
|
||||
:c:func:`PyObject_Free`, then this slot is not inherited but instead defaults
|
||||
to :c:func:`PyObject_GC_Del`.
|
||||
|
||||
:ref:`Heap subtypes <heap-types>` do not inherit this slot.
|
||||
|
||||
**Default:**
|
||||
|
||||
In dynamic subtypes, this field is set to a deallocator suitable to
|
||||
match :c:func:`PyType_GenericAlloc` and the value of the
|
||||
:c:macro:`Py_TPFLAGS_HAVE_GC` flag bit.
|
||||
For :ref:`heap subtypes <heap-types>`, this slot defaults to a deallocator suitable to match
|
||||
:c:func:`PyType_GenericAlloc` and the value of the
|
||||
:c:macro:`Py_TPFLAGS_HAVE_GC` flag.
|
||||
|
||||
For static subtypes, :c:data:`PyBaseObject_Type` uses :c:func:`PyObject_Free`.
|
||||
For static subtypes, this slot is inherited (see above).
|
||||
|
||||
|
||||
.. c:member:: inquiry PyTypeObject.tp_is_gc
|
||||
|
|
@ -2144,29 +2273,138 @@ and :c:data:`PyType_Type` effectively act as defaults.)
|
|||
|
||||
.. c:member:: destructor PyTypeObject.tp_finalize
|
||||
|
||||
An optional pointer to an instance finalization function. Its signature is::
|
||||
An optional pointer to an instance finalization function. This is the C
|
||||
implementation of the :meth:`~object.__del__` special method. Its signature
|
||||
is::
|
||||
|
||||
void tp_finalize(PyObject *self);
|
||||
|
||||
If :c:member:`~PyTypeObject.tp_finalize` is set, the interpreter calls it once when
|
||||
finalizing an instance. It is called either from the garbage
|
||||
collector (if the instance is part of an isolated reference cycle) or
|
||||
just before the object is deallocated. Either way, it is guaranteed
|
||||
to be called before attempting to break reference cycles, ensuring
|
||||
that it finds the object in a sane state.
|
||||
The primary purpose of finalization is to perform any non-trivial cleanup
|
||||
that must be performed before the object is destroyed, while the object and
|
||||
any other objects it directly or indirectly references are still in a
|
||||
consistent state. The finalizer is allowed to execute
|
||||
arbitrary Python code.
|
||||
|
||||
:c:member:`~PyTypeObject.tp_finalize` should not mutate the current exception status;
|
||||
therefore, a recommended way to write a non-trivial finalizer is::
|
||||
Before Python automatically finalizes an object, some of the object's direct
|
||||
or indirect referents might have themselves been automatically finalized.
|
||||
However, none of the referents will have been automatically cleared
|
||||
(:c:member:`~PyTypeObject.tp_clear`) yet.
|
||||
|
||||
Other non-finalized objects might still be using a finalized object, so the
|
||||
finalizer must leave the object in a sane state (e.g., invariants are still
|
||||
met).
|
||||
|
||||
.. note::
|
||||
|
||||
After Python automatically finalizes an object, Python might start
|
||||
automatically clearing (:c:member:`~PyTypeObject.tp_clear`) the object
|
||||
and its referents (direct and indirect). Cleared objects are not
|
||||
guaranteed to be in a consistent state; a finalized object must be able
|
||||
to tolerate cleared referents.
|
||||
|
||||
.. note::
|
||||
|
||||
An object is not guaranteed to be automatically finalized before its
|
||||
destructor (:c:member:`~PyTypeObject.tp_dealloc`) is called. It is
|
||||
recommended to call :c:func:`PyObject_CallFinalizerFromDealloc` at the
|
||||
beginning of :c:member:`!tp_dealloc` to guarantee that the object is
|
||||
always finalized before destruction.
|
||||
|
||||
.. note::
|
||||
|
||||
The :c:member:`~PyTypeObject.tp_finalize` function can be called from any
|
||||
thread, although the :term:`GIL` will be held.
|
||||
|
||||
.. note::
|
||||
|
||||
The :c:member:`!tp_finalize` function can be called during shutdown,
|
||||
after some global variables have been deleted. See the documentation of
|
||||
the :meth:`~object.__del__` method for details.
|
||||
|
||||
When Python finalizes an object, it behaves like the following algorithm:
|
||||
|
||||
#. Python might mark the object as *finalized*. Currently, Python always
|
||||
marks objects whose type supports garbage collection (i.e., the
|
||||
:c:macro:`Py_TPFLAGS_HAVE_GC` flag is set in
|
||||
:c:member:`~PyTypeObject.tp_flags`) and never marks other types of
|
||||
objects; this might change in a future version.
|
||||
#. If the object is not marked as *finalized* and its
|
||||
:c:member:`!tp_finalize` finalizer function is non-``NULL``, the
|
||||
finalizer function is called.
|
||||
#. If the finalizer function was called and the finalizer made the object
|
||||
reachable (i.e., there is a reference to the object and it is not a
|
||||
member of a :term:`cyclic isolate`), then the finalizer is said to have
|
||||
*resurrected* the object. It is unspecified whether the finalizer can
|
||||
also resurrect the object by adding a new reference to the object that
|
||||
does not make it reachable, i.e., the object is (still) a member of a
|
||||
cyclic isolate.
|
||||
#. If the finalizer resurrected the object, the object's pending destruction
|
||||
is canceled and the object's *finalized* mark might be removed if
|
||||
present. Currently, Python never removes the *finalized* mark; this
|
||||
might change in a future version.
|
||||
|
||||
*Automatic finalization* refers to any finalization performed by Python
|
||||
except via calls to :c:func:`PyObject_CallFinalizer` or
|
||||
:c:func:`PyObject_CallFinalizerFromDealloc`. No guarantees are made about
|
||||
when, if, or how often an object is automatically finalized, except:
|
||||
|
||||
* Python will not automatically finalize an object if it is reachable, i.e.,
|
||||
there is a reference to it and it is not a member of a :term:`cyclic
|
||||
isolate`.
|
||||
* Python will not automatically finalize an object if finalizing it would
|
||||
not mark the object as *finalized*. Currently, this applies to objects
|
||||
whose type does not support garbage collection, i.e., the
|
||||
:c:macro:`Py_TPFLAGS_HAVE_GC` flag is not set. Such objects can still be
|
||||
manually finalized by calling :c:func:`PyObject_CallFinalizer` or
|
||||
:c:func:`PyObject_CallFinalizerFromDealloc`.
|
||||
* Python will not automatically finalize any two members of a :term:`cyclic
|
||||
isolate` concurrently.
|
||||
* Python will not automatically finalize an object after it has
|
||||
automatically cleared (:c:member:`~PyTypeObject.tp_clear`) the object.
|
||||
* If an object is a member of a :term:`cyclic isolate`, Python will not
|
||||
automatically finalize it after automatically clearing (see
|
||||
:c:member:`~PyTypeObject.tp_clear`) any other member.
|
||||
* Python will automatically finalize every member of a :term:`cyclic
|
||||
isolate` before it automatically clears (see
|
||||
:c:member:`~PyTypeObject.tp_clear`) any of them.
|
||||
* If Python is going to automatically clear an object
|
||||
(:c:member:`~PyTypeObject.tp_clear`), it will automatically finalize the
|
||||
object first.
|
||||
|
||||
Python currently only automatically finalizes objects that are members of a
|
||||
:term:`cyclic isolate`, but future versions might finalize objects regularly
|
||||
before their destruction.
|
||||
|
||||
To manually finalize an object, do not call this function directly; call
|
||||
:c:func:`PyObject_CallFinalizer` or
|
||||
:c:func:`PyObject_CallFinalizerFromDealloc` instead.
|
||||
|
||||
:c:member:`~PyTypeObject.tp_finalize` should leave the current exception
|
||||
status unchanged. The recommended way to write a non-trivial finalizer is
|
||||
to back up the exception at the beginning by calling
|
||||
:c:func:`PyErr_GetRaisedException` and restore the exception at the end by
|
||||
calling :c:func:`PyErr_SetRaisedException`. If an exception is encountered
|
||||
in the middle of the finalizer, log and clear it with
|
||||
:c:func:`PyErr_WriteUnraisable` or :c:func:`PyErr_FormatUnraisable`. For
|
||||
example::
|
||||
|
||||
static void
|
||||
local_finalize(PyObject *self)
|
||||
foo_finalize(PyObject *self)
|
||||
{
|
||||
/* Save the current exception, if any. */
|
||||
// Save the current exception, if any.
|
||||
PyObject *exc = PyErr_GetRaisedException();
|
||||
|
||||
/* ... */
|
||||
// ...
|
||||
|
||||
/* Restore the saved exception. */
|
||||
if (do_something_that_might_raise() != success_indicator) {
|
||||
PyErr_WriteUnraisable(self);
|
||||
goto done;
|
||||
}
|
||||
|
||||
done:
|
||||
// Restore the saved exception. This silently discards any exception
|
||||
// raised above, so be sure to call PyErr_WriteUnraisable first if
|
||||
// necessary.
|
||||
PyErr_SetRaisedException(exc);
|
||||
}
|
||||
|
||||
|
|
@ -2182,7 +2420,13 @@ and :c:data:`PyType_Type` effectively act as defaults.)
|
|||
:c:macro:`Py_TPFLAGS_HAVE_FINALIZE` flags bit in order for this field to be
|
||||
used. This is no longer required.
|
||||
|
||||
.. seealso:: "Safe object finalization" (:pep:`442`)
|
||||
.. seealso::
|
||||
|
||||
* :pep:`442`: "Safe object finalization"
|
||||
* :ref:`life-cycle` for details about how this slot relates to other
|
||||
slots.
|
||||
* :c:func:`PyObject_CallFinalizer`
|
||||
* :c:func:`PyObject_CallFinalizerFromDealloc`
|
||||
|
||||
|
||||
.. c:member:: vectorcallfunc PyTypeObject.tp_vectorcall
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue