6

After checking numerous times, I did find inconsistent info about the topic.

In some case, I did find that __init__ and __del__ are the python equivalent of constructors and destructors. This seems to be true for __init__, since I see it called when the class is created; but __del__ is never called, when the program end.

In other cases, I did find that __del__ is bad, and you have to explicitly deallocate everything by hand.

Now, the issue is: which is which? Because using a unittest.TestCase class, when I call __del__ it never get called. Sadly I can't use tear down because I need to start a process before the tests run, and end it once I am done with the tests

  • @DYZ CPython uses reference counting, not garbage collection, so you can generally count on something being freed once every reference to it is gone. Other versions of Python may operate differently of course. – Mark Ransom Jan 07 '17 at 00:07
  • @MarkRansom Yep you are right. – DYZ Jan 07 '17 at 00:08
  • What do you mean by "when I call `__del__` it never get called"? How do you call it? This method (just like any other method whose name starts with `__`) should never be called by hand. It is called automatically when all references to the object are gone. In particular, when you execute `del` statement. – DYZ Jan 07 '17 at 00:09
  • 3
    I think if you want to be a pedant `__init__` is not technically a constructor, but an initializer (hence the name), and the constructor is [`__new__`](https://docs.python.org/3/reference/datamodel.html#object.__new__). – juanpa.arrivillaga Jan 07 '17 at 00:17
  • I don't think you even can explicitly deallocate memory in Python. – juanpa.arrivillaga Jan 07 '17 at 00:22
  • Unittest also has setup and teardown at the class and module level (cf the doc), and you can also write your own test runner if that's still not enough. – bruno desthuilliers Jan 07 '17 at 00:31
  • 3
    `__del__` does get called when there are no more references to the object. In the case of unittest TestCases, the runner is keeping a reference to them, so they're not going away. You should look at [`setUpClass()` and `tearDownClass()`](https://docs.python.org/2/library/unittest.html#setupclass-and-teardownclass). They're probably closer to what you want. – John Szakmeister Jan 07 '17 at 01:51
  • Good points everyone. I am used in C++ with constructors and destructors; things happens based on where the code is placed; but in python is not that simple, from the flow perspective. __del__ never get called when the test finish; this is what I meant. I do not call neither __init__ nor __del__ explicitly, because __init__ is called when the class is created and the application run, so I was expecting the same with __end__, once the application is done, but I see that I need to use setupClass and tearDownClass, to get a similar behavior. Thanks! –  Jan 07 '17 at 02:58

1 Answers1

12

There are few SO posts in which this kind of behavior that you see, namely for example that __del__ doesn't gets called, is kind of discussed. To name a few sources that I found interesting, both SO and the __del__ documentation:
What is the __del__ method, How to call it?
I don't understand this python __del__ behaviour
https://docs.python.org/3/reference/datamodel.html#object.del

I found especially illuminating the section from the documentation:

Note: 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. Some common situations that may prevent the reference count of an object from going to zero include: circular references between objects (e.g., a doubly-linked list or a tree data structure with parent and child pointers); a reference to the object on the stack frame of a function that caught an exception (the traceback stored in sys.exc_info()2 keeps the stack frame alive); or a reference to the object on the stack frame that raised an unhandled exception in interactive mode (the traceback stored in sys.last_traceback keeps the stack frame alive). The first situation can only be remedied by explicitly breaking the cycles; the second can be resolved by freeing the reference to the traceback object when it is no longer useful, and the third can be resolved by storing None in sys.last_traceback. Circular references which are garbage are detected and cleaned up when the cyclic garbage collector is enabled (it’s on by default). Refer to the documentation for the gc module for more information about this topic.

So there are clearly cases in which __del__ might not be called because the reference count of an object hasn't reached zero and in the note few cases are listed in which this situation might happen.

Community
  • 1
  • 1
fedepad
  • 4,509
  • 1
  • 13
  • 27
  • The part related to the reference count is really interesting; thanks for the links –  Jan 07 '17 at 02:59