mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
Close #19047: weakref doc cleanups
- be clear finalizers survive automatically - update for PEP 442 __del__ changes - mention module cleanup changes and weakref.finalize in What's New
This commit is contained in:
parent
a2838878fa
commit
be57ab8a34
2 changed files with 47 additions and 21 deletions
|
@ -54,7 +54,8 @@ but keeps weak references to its elements, just like a
|
||||||
:class:`finalize` provides a straight forward way to register a
|
:class:`finalize` provides a straight forward way to register a
|
||||||
cleanup function to be called when an object is garbage collected.
|
cleanup function to be called when an object is garbage collected.
|
||||||
This is simpler to use than setting up a callback function on a raw
|
This is simpler to use than setting up a callback function on a raw
|
||||||
weak reference.
|
weak reference, since the module automatically ensures that the finalizer
|
||||||
|
remains alive until the object is collected.
|
||||||
|
|
||||||
Most programs should find that using one of these weak container types
|
Most programs should find that using one of these weak container types
|
||||||
or :class:`finalize` is all they need -- it's not usually necessary to
|
or :class:`finalize` is all they need -- it's not usually necessary to
|
||||||
|
@ -246,11 +247,14 @@ These method have the same issues as the and :meth:`keyrefs` method of
|
||||||
.. class:: finalize(obj, func, *args, **kwargs)
|
.. class:: finalize(obj, func, *args, **kwargs)
|
||||||
|
|
||||||
Return a callable finalizer object which will be called when *obj*
|
Return a callable finalizer object which will be called when *obj*
|
||||||
is garbage collected. A finalizer is *alive* until it is called
|
is garbage collected. Unlike an ordinary weak reference, a finalizer is
|
||||||
(either explicitly or at garbage collection), and after that it is
|
will always survive until the reference object is collected, greatly
|
||||||
*dead*. Calling a live finalizer returns the result of evaluating
|
simplifying lifecycle management.
|
||||||
``func(*arg, **kwargs)``, whereas calling a dead finalizer returns
|
|
||||||
:const:`None`.
|
A finalizer is considered *alive* until it is called (either explicitly
|
||||||
|
or at garbage collection), and after that it is *dead*. Calling a live
|
||||||
|
finalizer returns the result of evaluating ``func(*arg, **kwargs)``,
|
||||||
|
whereas calling a dead finalizer returns :const:`None`.
|
||||||
|
|
||||||
Exceptions raised by finalizer callbacks during garbage collection
|
Exceptions raised by finalizer callbacks during garbage collection
|
||||||
will be shown on the standard error output, but cannot be
|
will be shown on the standard error output, but cannot be
|
||||||
|
@ -445,8 +449,9 @@ objects can still be retrieved by ID if they do.
|
||||||
Finalizer Objects
|
Finalizer Objects
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Often one uses :class:`finalize` to register a callback without
|
The main benefit of using :class:`finalize` is that it makes it simple
|
||||||
bothering to keep the returned finalizer object. For instance
|
to register a callback without needing to preserve the returned finalizer
|
||||||
|
object. For instance
|
||||||
|
|
||||||
>>> import weakref
|
>>> import weakref
|
||||||
>>> class Object:
|
>>> class Object:
|
||||||
|
@ -489,7 +494,7 @@ the constructor when it was created.
|
||||||
CALLBACK
|
CALLBACK
|
||||||
|
|
||||||
Unless you set the :attr:`~finalize.atexit` attribute to
|
Unless you set the :attr:`~finalize.atexit` attribute to
|
||||||
:const:`False`, a finalizer will be called when the program exit if it
|
:const:`False`, a finalizer will be called when the program exits if it
|
||||||
is still alive. For instance
|
is still alive. For instance
|
||||||
|
|
||||||
>>> obj = Object()
|
>>> obj = Object()
|
||||||
|
@ -529,13 +534,18 @@ follows::
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.remove()
|
self.remove()
|
||||||
|
|
||||||
This solution has a serious problem: the :meth:`__del__` method may be
|
Starting with Python 3.4, :meth:`__del__` methods no longer prevent
|
||||||
called at shutdown after the :mod:`shutil` module has been cleaned up,
|
reference cycles from being garbage collected, and module globals are
|
||||||
in which case :attr:`shutil.rmtree` will have been replaced by :const:`None`.
|
no longer forced to :const:`None` during interpreter shutdown. So this
|
||||||
This will cause the :meth:`__del__` method to fail and the directory
|
code should work without any issues on CPython.
|
||||||
will not be removed.
|
|
||||||
|
|
||||||
Using finalizers we can avoid this problem::
|
However, handling of :meth:`__del__` methods is notoriously implementation
|
||||||
|
specific, since it depends on how the interpreter's garbage collector
|
||||||
|
handles reference cycles and finalizers.
|
||||||
|
|
||||||
|
A more robust alternative can be to define a finalizer which only references
|
||||||
|
the specific functions and objects that it needs, rather than having access
|
||||||
|
to the full state of the object::
|
||||||
|
|
||||||
class TempDir:
|
class TempDir:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -549,10 +559,19 @@ Using finalizers we can avoid this problem::
|
||||||
def removed(self):
|
def removed(self):
|
||||||
return not self._finalizer.alive
|
return not self._finalizer.alive
|
||||||
|
|
||||||
Defined like this, even if a :class:`TempDir` object is part of a
|
Defined like this, our finalizer only receives a reference to the details
|
||||||
reference cycle, that reference cycle can still be garbage collected.
|
it needs to clean up the directory appropriately. If the object never gets
|
||||||
If the object never gets garbage collected the finalizer will still be
|
garbage collected the finalizer will still be called at exit.
|
||||||
called at exit.
|
|
||||||
|
The other advantage of weakref based finalizers is that they can be used to
|
||||||
|
register finalizers for classes where the definition is controlled by a
|
||||||
|
third party, such as running code when a module is unloaded::
|
||||||
|
|
||||||
|
import weakref, sys
|
||||||
|
def unloading_module():
|
||||||
|
# implicit reference to the module globals from the function body
|
||||||
|
weakref.finalize(sys.modules[__name__], unloading_module)
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
|
|
@ -153,6 +153,10 @@ With it, objects with :meth:`__del__` methods, as well as generators
|
||||||
with :keyword:`finally` clauses, can be finalized when they are part of a
|
with :keyword:`finally` clauses, can be finalized when they are part of a
|
||||||
reference cycle.
|
reference cycle.
|
||||||
|
|
||||||
|
As part of this change, module globals are no longer forcibly set to
|
||||||
|
:const:`None` during interpreter shutdown, instead relying on the normal
|
||||||
|
operation of the cyclic garbage collector.
|
||||||
|
|
||||||
.. seealso::
|
.. seealso::
|
||||||
|
|
||||||
:pep:`442` - Safe object finalization
|
:pep:`442` - Safe object finalization
|
||||||
|
@ -416,9 +420,12 @@ weakref
|
||||||
-------
|
-------
|
||||||
|
|
||||||
New :class:`~weakref.WeakMethod` class simulates weak references to bound
|
New :class:`~weakref.WeakMethod` class simulates weak references to bound
|
||||||
methods.
|
methods. (Contributed by Antoine Pitrou in :issue:`14631`.)
|
||||||
|
|
||||||
(Contributed by Antoine Pitrou in :issue:`14631`.)
|
New :class:`~weakref.finalize` class makes it possible to register a callback
|
||||||
|
to be invoked when an object is garbage collected, without needing to
|
||||||
|
carefully manage the lifecycle of the weak reference itself. (Contributed by
|
||||||
|
Richard Oudkerk in :issue:`15528`)
|
||||||
|
|
||||||
|
|
||||||
xml.etree
|
xml.etree
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue