When the interpreter exits normally, in such ways as the program ending or sys.exit
being called, not all objects are guaranteed to be destroyed. There is probably some amount of logic to this, but not very simple logic. After all, the __del__
method is for freeing memory resources, not other resources (like network connections) - that's what __enter__
and __exit__
are for.
Having said that, there are situtations in which __del__
will most certainly not be called. The parallel to this is atexit
functions; they are usually run at exit. However:
Note: The functions registered via this module are not called when the program is killed by a signal not handled by Python, when a Python fatal internal error is detected, or when os._exit()
is called.
atexit
documentation
So, there are situations in which clean-up functions, like __del__
, __exit__
, and functions registered with atexit
will not be called:
The program is killed by a signal not handled by Python - If a program recieves a signal to stop, like SIGINT or SIGQUIT, and it doesn't handle the signal, then it will be stopped.
A Python fatal interpreter error occurs.
os._exit()
is called - the documentation says:
Exit the process with status n, without calling cleanup handlers, flushing stdio buffers, etc.
So it is pretty clear that __del__
should not be called.
In conclusion, the interpreter does not guarantee __del__
being called, but there are situations in which it will definitely not be called.