Exception error when accessing the class variable at the termination of the program

Chris Rebert clp2 at rebertia.com
Mon Feb 2 10:37:08 CET 2009


On Sun, Feb 1, 2009 at 11:52 PM,  <jwalana at vsnl.net> wrote:
> Hi All,
>
>   Here is a sample piece of code with which I am having a problem, with Python version 2.4.4
>
> class Person:
>    Count = 0   # This represents the count of objects of this class
>
>    def __init__(self, name):
>        self.name = name
>        print name, ' is now created'
>        Person.Count += 1
>
>    def __del__(self):
>        print self.name, ' is now deleted'
>        Person.Count -= 1
>        if Person.Count == 0:
>            print 'The last object of Person class is now deleted'
>        else:
>            print 'There are still', Person.Count, ' objects of class Person'
>
> x2 = Person("Krishna")
> del x2
>
>  When the above code is executed, it works properly.
>
>  If the last statement del x2, is removed, then when the program terminates, this throws up an exception as shown below
>
> Krishna  is now created
> Krishna  is now deleted
> Exception exceptions.AttributeError: "'NoneType' object has no attribute 'Count'
> " in <bound method Person.__del__ of <__main__.Person instance at 0xf6532f6c>> ignored
>
>  Can someone please explain why the exception happens in the case where there is no explicit del statement?

Without the `del`, the reference count of x2 remains >0 and so is not
deleted until the program ends. This affects when __del__ is executed,
which matters greatly.

>From the section on __del__ on
http://www.python.org/doc/2.3.5/ref/customization.html :
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***. For this reason,
__del__() methods should do the absolute minimum needed to maintain
external invariants. [etc., emphasis mine]

Since without the `del`, __del__ is only called at the end of the
program, Person and/or Count may have already been GC-ed by the time
__del__ is called (the order objects are GC-ed in is a bit
unpredictable), hence the error you get which is saying, in a slightly
obtuse way, that Person has been GC-ed already.
As the Warning states, __del__ shouldn't be relied upon to do fancy
stuff like you're having it do. You would be better off using an
explicit finalizer method in this case, like .close() for file
objects.

For example:

try:
    x2 = Person("Krishna")
    #do stuff with x2
finally:
    x2.delete() #causes count to be decremented

Cheers,
Chris
-- 
Follow the path of the Iguana...
http://rebertia.com



More information about the Python-list mailing list