1

Say I have some class that manages a database connection. The user is supposed to call close() on instances of this class so that the db connection is terminated cleanly.

Is there any way in python to get this object to call close() if the interpreter is closed or the object is otherwise picked up by the garbage collector?

Edit: This question assumes the user of the object failed to instantiate it within a with block, either because he forgot or isn't concerned about closing connections.

Matthew Moisen
  • 16,701
  • 27
  • 128
  • 231
  • 1
    Maybe [this](http://stackoverflow.com/questions/865115/how-do-i-correctly-clean-up-a-python-object) can help you. Use your object with a `with` statement by implementing `__enter__` and `__exit__` method. – pixis Mar 18 '16 at 04:17
  • @Hackndo sorry, I should have specified that the question assumes the user forgot to instantiate the object within a `with` block. – Matthew Moisen Mar 18 '16 at 04:23
  • You could try using `__del__`, but that is not guaranteed to be called if the object is still in scope when the program exits. The user really needs to be responsible and use `with`. – chepner Mar 18 '16 at 04:26
  • @chepner does `__del__` method get called sometimes when the program exits? If so I might as well throw a call to `close()` inside of `__del__`. – Matthew Moisen Mar 18 '16 at 06:30

2 Answers2

2

The only way to ensure such a method is called if you don't trust users is using __del__ (docs). From the docs:

Called when the instance is about to be destroyed.

Note that there are lots of issues that make using del tricky. For example, at the moment it is called, the interpreter may be shutting down already - meaning other objects and modules may have been destroyed already. See the notes and warnings for details.


If you really cannot rely on users to be consenting adults, I would prevent them from implicitly avoiding close - don't give them a public open in the first place. Only supply the methods to support with. If anybody explicitly digs into your code to do otherwise, they probably have a good reason for it.

MisterMiyagi
  • 44,374
  • 10
  • 104
  • 119
1

Define __enter__ and __exit__ methods on your class and then use it with the with statement:

with MyClass() as c:
    # Do stuff

When the with block ends your __exit__() method will be called automatically.

ChrisGPT was on strike
  • 127,765
  • 105
  • 273
  • 257
  • Sorry, I should have specified that the question assumes the user failed to instantiate the object within a `with` block, because he either forgot to or didn't care about closing the connection. – Matthew Moisen Mar 18 '16 at 04:23
  • 1
    You can probably put the behaviour you want in [`__del__`](https://docs.python.org/2/reference/datamodel.html#object.__del__) if you really want to, but in my opinion `__enter__`, `__exit__` and `with` are a better fit. `__del__` might not get called in all circumstances, e.g. "It is not guaranteed that `__del__()` methods are called for objects that still exist when the interpreter exits". – ChrisGPT was on strike Mar 18 '16 at 04:28