Alex Bochkarev
Alex Bochkarev

Reputation: 2981

Which objects are not destroyed upon Python interpreter exit?

According to Python documentation:

It is not guaranteed that __del__() methods are called for objects that still exist when the interpreter exits.

I know that in older versions of Python cyclic referencing would be one of the examples for this behaviour, however as I understand it, in Python 3 such cycles will successfully be destroyed upon interpreter exit.

I'm wondering what are the cases (as close to exhaustive list as possible) when the interpreter would not destroy an object upon exit.

Upvotes: 17

Views: 1076

Answers (3)

S.B
S.B

Reputation: 16476

After comparing the quoted sentence from documentation and your title, I thought you misunderstood what __del__ is and what it does.

You used the word "destroyed", and documentation said __del__ may not get called in some situations... The thing is "all" objects are get deleted after the interpreter's process finishes. __del__ is not a destructor and has nothing to do with the destruction of objects. Even if a memory leakage occurs in a process, operating systems(the ones I know at least: Linux, Windows,...) will eventually reclaim that memory for the process after it finishes. So everything is destroyed/deleted!(here and here)

In normal cases when these objects are about to get destroyed, __del__ (better known as finalizer) gets called in the very last step of destruction. In other cases mentioned by other answers, It doesn't get called.

That's why people say don't count on __del__ method for cleaning vital stuff and instead use a context manager. In some scenarios, __del__ may even revive the object by passing a reference around.

Upvotes: 1

pigrammer
pigrammer

Reputation: 3489

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:

  1. 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.

  2. A Python fatal interpreter error occurs.

  3. 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.

Upvotes: 7

user2357112
user2357112

Reputation: 280380

All examples are implementation details - Python does not promise whether or not it will call __del__ for any particular objects on interpreter exit. That said, one of the simplest examples is with daemon threads:

import threading
import time

def target():
    time.sleep(1000)

class HasADel:
    def __del__(self):
        print('del')

x = HasADel()

threading.Thread(target=target, daemon=True).start()

Here, the daemon thread prevents the HasADel instance from being garbage collected on interpreter shutdown. The daemon thread doesn't actually do anything with that object, but Python can't clean up references the daemon thread owns, and x is reachable from references the daemon thread owns.

Upvotes: 13

Related Questions