Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pythonic way to close connection-like objects in __del__

Tags:

python

I'm working on a connection-like object which implements a context manager. Writing something like this is strongly encouraged:

with MyConnection() as con:
    # do stuff

Of course one can do this as well:

con = MyConnection()
# do stuff
con.close()

But failing to close the connection is rather problematic. So closing in the __del__() seems like a good idea:

def __del__(self):
    self.close()

This looks quite nice, but sometimes leads to errors:

Exception ignored in: [...]
Traceback (most recent call last):
  File "...", line xxx, in __del__()
TypeError: 'NoneType' object is not callable

It appears as if sometimes the close method is already destroyed, when __del__() is called.

So I'm looking for a nice way to encourage python to close the connection properly on destruction. If possible I would like to avoid code duplication in close() and __del__()

like image 770
cel Avatar asked Dec 07 '22 01:12

cel


1 Answers

If you really want to prevent the user from not closing the connection, you could just init it only in __enter__ or you may add a flag spotting the fact it has not been initialized by a context manager. For instance, something like

class MyConnection(object):

    safely_initialized = False

    def __enter__(self):
        # Init your connection
        self.safely_initialized = True
        return self

    def do_something(self):
        if not self.safely_initialized:
            raise Exception('You must initialize the connection with a context manager!')
        # Do something

    def __exit__(self, type, value, traceback):
        # Close your connection

That way the connection won't be initialized unless within a context manager.

like image 108
Seb D. Avatar answered Dec 08 '22 16:12

Seb D.