__del__ is very useful not for interpreter shutdown but as a regular
destructor in object's lifecycle.
Oh, I'm absolutely thinking about clarity. ...
Could any revision also be clear what is *required of Python the
language* vs. what is a CPython implementation detail? I always
appreciate this care. There is good practice here and elsewhere in
the existing documentation, but drift is easy for those steeped in
CPython implementation. In the present case, it's a matter of
avoiding an explicit requirement for a reference-counting approach
to lifecycle management. Here the places in the proposal a change
could achieve that.
The precise semantics of when __del__ is called on an object are implementation-dependent. For example:
* It might be invoked during the normal interpreter flow at a moment like function return, ...
We should continue here "... immediately the object is no nonger referenced;"
(It might not be called immediately, but that's implied by your
implementation-dependent "might be".)
Note that del x doesn’t directly call x.__del__() — the former decrements the reference count for x by one, and the latter is only called when x’s reference count reaches zero. Depending on the implementation, it is possible for a reference cycle to prevent the reference count of an object from going to zero. (e.g., in CPython, a common cause of reference cycles is when an exception is caught and stored in a local variable; the exception contains a reference to the traceback, which in turn references the locals of all frames caught in the traceback.) In this case, the cycle will be later detected and deleted by the cyclic garbage collector.
I realise that most of this paragraph is existing text rearranged, and currently it fails to make the distinction I'm looking for in the "note" part. But it is clear in the next paragraph. I think it better to say, closer to the current text:
"""Note:: ``del x`` does not call ``x.__del__()`` directly. After
``del x``, variable ``x`` is undefined (or unbound). If the object
it referenced is now no longer referenced at all, that object's
``__del__()`` might be called, immediately or later, subject to
the caveats already given.
*CPython implementation detail:* ``del x`` decrements the reference count of the object by one, and if that makes it zero, ``x.__del__()`` will be called immediately. It is possible for a reference cycle to prevent the reference count of any object in it from going to zero. A common cause of reference cycles is when an exception is caught and stored in a local variable; the exception contains a reference to the traceback, which in turn references the locals of all frames caught in the traceback. In this case, the cycle will be detected later and its objects deleted by the cyclic garbage collector."""
If a base class has a __del__() method, the derived class’s __del__() method, if any, must explicitly call it to ensure proper deletion of the base class part of the instance.
Possibly this thought belings with the "implementations of __del__(): * Must ..." paragraph.
But also, while I think there is scope for a better guidance,
this is getting a bit long. Should there be a "HOW TO write a
__del__ method (and how to avoid it)" to contain the advisory
points being made? In-lining advice here, on how to survive the
infernal circles of __del__, dilutes the scariness of the warning
not to enter at all.
---
Jeff Allen
_______________________________________________
Python-Dev mailing list -- pytho...@python.org
To unsubscribe send an email to python-d...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/pytho...@python.org/message/A32QEUP4R6XTY5LQW56LKWJ3XBUZCHOR/
weakref.finalize always executes during the ordinary Python flow, IIUC -- e.g., it happens before the interpreter is stopping. I guess it does still have the "arbitrary thread" limitation -- which is a good point, I may have some code bugs of my own to fix. But it's a huge difference in terms of predictability of the interpreter state, and in particular both the issues around deleted modules and the ones around threading no longer working don't apply to it.atexit is a pretty corner-case thing -- I agree that it shouldn't be the common thing at all, and the recommendation should be specifically for those use cases where it makes sense.