[Python-Dev] Is there any remaining reason why weakref callbacks shouldn't be able to access the referenced object?

Armin Rigo armin.rigo at gmail.com
Sun Jan 15 05:43:24 EST 2017


Hi,

Sorry to reply in this old thread.  We just noticed this on #pypy:

On 22 October 2016 at 05:32, Nick Coghlan <ncoghlan at gmail.com> wrote:
> The weakref-before-__del__ ordering change in
> https://www.python.org/dev/peps/pep-0442/#disposal-of-cyclic-isolates
> only applies to cyclic garbage collection,so for normal refcount
> driven object cleanup in CPython, the __del__ still happens first:
>
>     >>> class C:
>     ...     def __del__(self):
>     ...         print("__del__ called")
>     ...
>     >>> c = C()
>     >>> import weakref
>     >>> def cb():
>     ...     print("weakref callback called")
>     ...
>     >>> weakref.finalize(c, cb)
>     <finalize object at 0x7f4300b710a0; for 'C' at 0x7f42f8ae3470>
>     >>> del c
>     __del__ called
>     weakref callback called

Nick, it seems you're suggesting that before PEP 442 (in CPython 3.4)
the __del__ happened before the weakref-clearing operation as well.
That's not the case: before CPython 3.4, weakrefs are always cleared
first.  The situation became more muddy in 3.4, where weakrefs are
usually cleared after the __del__ is called---in the absence of
reference cycles (so it's a backward-incompatible change).  If there
are reference cycles, then the weakref is cleared before the __del__
is called.

This can be shown in your example by replacing "weakref.finalize(c,
cb)" with an old-style "wr = weakref.ref(c, cb)".  Then CPython <= 3.3
and >= 3.4 print the two lines in opposite order.


A bientôt,

Armin.


More information about the Python-Dev mailing list