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

2009-02-02 Thread Duncan Booth
jwal...@vsnl.net wrote:

>  Can someone please explain why the exception happens in the case
>  where there is no explicit del statement? 

When Python is ecleaning up as it exits, it clears all the global 
variables in each module by setting them to None. This happens in an 
arbitrary and unpredictable order: in this particular case it set Person 
to None before setting x2 to None.

If you must have a __del__ method on a class then you should take care 
not to access any globals from inside the __del__ method (or any 
function it calls). Alternatively you could just catch and ignore any 
exceptions thrown from your __del__ method.

In the example you gave, provided you never subclass Person you could 
use self.__class__.Count to access your class variable. However in many 
cases you'll probably find that a much better solution is to use weak 
references. e.g. a WeakValueDictionary mapping id(self) to self:

from weakref import WeakValueDictionary

class Person:
_instances = WeakValueDictionary()

def __init__(self, name):
self.name = name
self._instances[id(self)] = self
print name, 'is now created'

@property
def Count(self):
return len(self._instances)

def __del__(self):
print self.name, 'is now deleted'
if self.Count==0:
print 'The last object of Person class is now deleted'
else:
print 'There are still', self.Count, 'objects of class 
Person'

x2 = Person('Krishna')
# del x2


-- 
Duncan Booth http://kupuguy.blogspot.com
--
http://mail.python.org/mailman/listinfo/python-list


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

2009-02-02 Thread Chris Rebert
On Sun, Feb 1, 2009 at 11:52 PM,   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  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
--
http://mail.python.org/mailman/listinfo/python-list


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

2009-02-02 Thread jwalana
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 > 
ignored

 Can someone please explain why the exception happens in the case where there 
is no explicit del statement?

Thanks
Jana

--
http://mail.python.org/mailman/listinfo/python-list