3

I want use ConfigParser in one class, it needs a call from the destructor, but then strange things happen.

This is my code:

"""
function name is 
test  ok!
test1 failed!
test2 failed!
test3 failed!

test4
...  ok!

"""

def test3():
  pass

class Class1:
  def __del__(self):
    test3()

if __name__=="__main__":
  obj=Class1()

If the function is named test1, test2 or test3, an exception will be raised, and I can't catch it by try except.

The traceback is:

E:\tc.py
Exception TypeError: "'NoneType' object is not callable" in <bound method Class1.__del__ of <__main__.Class1 instance at 0x00C18F58>> ignored

It's so strange! Can you test it in your system? Or am I doing something wrong?

Maehler
  • 6,111
  • 1
  • 41
  • 46

2 Answers2

11

The order in which objects are destroyed is undefined. This means that by the time obj.__del__() is called -- if it's called at all -- test3() may or may not have been destroyed.

There is a red box with a warning in the documentation:

Warning Due to the precarious circumstances under which __del__() methods are invoked, exceptions that occur during their execution are ignored, and a warning is printed to sys.stderr instead. Also, when __del__() is invoked in response to a module being deleted (e.g., when execution of the program is done), other globals referenced by the __del__() method may already have been deleted or in the process of being torn down (e.g. the import machinery shutting down). For this reason, __del__() methods should do the absolute minimum needed to maintain external invariants. Starting with version 1.5, Python guarantees that globals whose name begins with a single underscore are deleted from their module before other globals are deleted; if no other references to such globals exist, this may help in assuring that imported modules are still available at the time when the __del__() method is called.

In Python, one almost never overrides __del__. You should probably rethink your design. See How do I correctly clean up a Python object?

Community
  • 1
  • 1
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • it's perfect answer. I used to save-work in destructor , just like in C++ . it is mistake in python , I get this red box. – weimingzhen May 30 '12 at 07:38
  • 1
    @weimingzhen: That's right, Python's `__del__` is more similar to Java's finalizers than to C++ destructors. In modern Python, the `with` statement is the correct idiom for freeing up resources (`try`-`finally` being a distant second). – NPE May 30 '12 at 07:47
4

You can't be certain that test3 hasn't been destroyed by the time obj.__del__() is called. Add a reference to it in Class1.__init__() if you need to keep it around.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358