__del__ and reference count problem

F

flupke

Hi,

i'm starting work and a simple database layer and wanted to use the
__del__ to open and close a connection. However, i get an erro when
executing this script:

class Table:
refcount = 0
def __init__(self, name):
self.name = name
print "table %s " % repr(self)
Table.refcount += 1
print "refcount = %s" % str(Table.refcount)

def __del__(self):
Table.refcount -= 1
if (Table.refcount == 0):
print "Last table standing"
else:
print "There is/are still %d table(s) left." % Table.refcount

def __getitem__(self,item):
return "not implemented"

def howMany(self):
if (Table.refcount == 1):
print "Only 1 table"
else:
print "There are %d tables active." % Table.refcount

if __name__ == '__main__':
suppliera = Table("suppliers")
supplierb = Table("suppliers")
print "Supplier returned from a %s: %s" % (1, suppliera[1])
print "Supplier returned from b %s: %s" % (2, supplierb[2])
suppliera.howMany()
supplierb.howMany()

This produces the following output and error:
table <__main__.Table instance at 0x008D5C10>
refcount = 1
table <__main__.Table instance at 0x008D5C38>
refcount = 2
Supplier returned from a 1: not implemented
Supplier returned from b 2: not implemented
There are 2 tables active.
There are 2 tables active.
Exception exceptions.AttributeError: "'NoneType' object has no attribute
'refcount'" in <bound method Table.__del__ of <__main__.Table instance
at 0x008D5C10>> ignored
Exception exceptions.AttributeError: "'NoneType' object has no attribute
'refcount'" in <bound method Table.__del__ of <__main__.Table instance
at 0x008D5C38>> ignored

What am i doing wrong?
Thanks
Benedict
 
A

ajikoe

Your problem can be simplified :

class A:
pop = 11
def __del__(self):
print A.pop

if __name__ == '__main__':
objA = A()

Exception exceptions.AttributeError: "'NoneType' object has no
attribute 'pop'" in <bound method A.__del__ of <__main__.A instance at
0x01474A08>> ignored

I got the same error message, and I don't know why ? it looks like the
class variable can't be accessed from __del__?


Pujo
 
F

Fredrik Lundh

Your problem can be simplified :

class A:
pop = 11
def __del__(self):
print A.pop

if __name__ == '__main__':
objA = A()

Exception exceptions.AttributeError: "'NoneType' object has no
attribute 'pop'" in <bound method A.__del__ of <__main__.A instance at
0x01474A08>> ignored

I got the same error message, and I don't know why ? it looks like the
class variable can't be accessed from __del__?

when Python shuts down, modules are sometimes cleaned out before objects
created from classes in those modules. if you really need to access a global
object during finalization, you have to hold on to it yourself.

def __del__(self, A=A):
print A.pop

(the best solution is to avoid using finalizers, of course, but that's another story)

</F>
 
T

tiissa

Your problem can be simplified :

class A:
pop = 11
def __del__(self):
print A.pop

if __name__ == '__main__':
objA = A()

I got the same error message, and I don't know why ? it looks like the
class variable can't be accessed from __del__?

It's interesting to note that self.pop instead of A.pop works as expected.
But I don't know why A.pop doesn't.
 
F

flupke

look at this discussion:
http://www.dbforums.com/archive/index.php/t-1100372.html

it looks like we have to use other way, hold the data we want to
preseve in an object, because it is possible the class is removed
before the instance cleaned, and we can not expect __del__ 100% in
handling finalizing process.

Pujo

That forum helped. I changed this in my code and it worked
def __del__(self):
self.__class__.refcount -= 1
if (self.__class__.refcount == 0):
print "Last table standing"
else:
print "There is/are still %d table(s) left." %
self.__class__.refcount

Output:
table <__main__.Table instance at 0x009D5B98>
refcount = 1
table <__main__.Table instance at 0x009D5BC0>
refcount = 2
Supplier returned from a 1: not implemented
Supplier returned from b 2: not implemented
There are 2 tables active.
There are 2 tables active.
There is/are still 1 table(s) left.
Last table standing

Seems to work allright !

Thanks ! :)
Benedict
 
T

Terry Reedy

it looks like we have to use other way, hold the data we want to
preseve in an object, because it is possible the class is removed
before the instance cleaned,

What is removed first is the binding between name A and the class object.
But the class object still exists (its refcount is > 0) and can be accessed
via the instance which has a reference to that class object.

Terry J. Reedy
 
T

Terry Reedy

tiissa said:
It's interesting to note that self.pop instead of A.pop works as
expected.
But I don't know why A.pop doesn't.

Because the name 'A' is no longer associated with the class object.
However, self has a reference to the class -- the .__class__ attribute.
Since self does not itself have a .pop attribute, the attribute resolution
code then looks at the class.

Terry J. Reedy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,731
Latest member
MarcyGipso

Latest Threads

Top