a Python bug in processing __del__ method ??

B

Baoqiu Cui

Today I was playing with a small Python program using Python 2.4
on Cygwin (up-to-date version, on Windows XP), but ran into a
strange error on the following small program (named bug.py):

-------------------------------
#!/usr/bin/python

class Person:
population = 0
def __del__(self):
Person.population -= 1

peter = Person()
-------------------------------

The error returned is this:

$ python bug.py
Exception exceptions.AttributeError: "'NoneType' object has no
attribute 'population'" in <bound method Person.__del__ of
<__main__.Person instance at 0xa0c9fec>> ignored

However, if I rename variable name 'peter' to something like 'peter1'
or 'david', the error is gone. Looks to me the
error only happens to variable name 'peter'.

Does anyone know what is wrong? Is this a bug only on Cygwin?
- Baoqiu
 
F

Fredrik Lundh

Baoqiu said:
The error returned is this:

$ python bug.py
Exception exceptions.AttributeError: "'NoneType' object has no
attribute 'population'" in <bound method Person.__del__ of
<__main__.Person instance at 0xa0c9fec>> ignored

However, if I rename variable name 'peter' to something like 'peter1'
or 'david', the error is gone. Looks to me the
error only happens to variable name 'peter'.

Does anyone know what is wrong? Is this a bug only on Cygwin?

it is not a bug, and the documentation has the answer:

language reference -> index -> __del__

http://docs.python.org/ref/customization.html#l2h-175

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.

if you absolutely need to have reliable access to globals, you need to make
sure they're available as instance variables, or are bound in some other way.

</F>
 
S

Steven Bethard

Baoqiu said:
Today I was playing with a small Python program using Python 2.4
on Cygwin (up-to-date version, on Windows XP), but ran into a
strange error on the following small program (named bug.py):

-------------------------------
#!/usr/bin/python

class Person:
population = 0
def __del__(self):
Person.population -= 1

peter = Person()
-------------------------------

The error returned is this:

$ python bug.py
Exception exceptions.AttributeError: "'NoneType' object has no
attribute 'population'" in <bound method Person.__del__ of
<__main__.Person instance at 0xa0c9fec>> ignored

However, if I rename variable name 'peter' to something like 'peter1'
or 'david', the error is gone. Looks to me the
error only happens to variable name 'peter'.

Does anyone know what is wrong? Is this a bug only on Cygwin?

I get this error on a normal Python WinXP install too. Looks like
Python deletes globals in order when exiting, so the Person class gets
deleted before the Person instances:

---------- bug.py ----------
class Person(object):
population = 0
def __del__(self):
Person.population -= 1

<name> = Person()
print list(globals())
----------------------------

I tried this with a few different names. Here are the results for
'apple', 'banana' and 'cranberry'. Only when the name appears after
'Person' in the globals do I get the error that you get.

[D:\Steve]$ bug.py
['apple', '__builtins__', '__file__', 'Person', '__name__', '__doc__']

[D:\Steve]$ bug.py
['__builtins__', '__file__', 'banana', 'Person', '__name__', '__doc__']

[D:\Steve]$ bug.py
['__builtins__', '__file__', 'Person', 'cranberry', '__name__', '__doc__']
Exception exceptions.AttributeError: "'NoneType' object has no attribute
'population'" in <bound method Person.__del__ of <__main__.Person object
at 0x009D1A50>> ignored

I don't know whether this is a bug or a "feature". ;)

Steve
 
S

Steven Bethard

Fredrik said:
it is not a bug, and the documentation has the answer:

language reference -> index -> __del__

http://docs.python.org/ref/customization.html#l2h-175

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.

if you absolutely need to have reliable access to globals, you need to make
sure they're available as instance variables, or are bound in some other way.

Along these lines, I think changing your code to:

class Person(object):
population = 0
def __del__(self):
self.__class__.population -= 1

peter = Person()

solves the problem. (At least it did for me.)

Steve
 
B

Baoqiu Cui

Fredrik and Steve,

Thank you so much for the help. Now I know more about Python. :)

Steve's test does explain why 'peter1' is OK while 'peter' is not:
'peter1' appears
before 'Person' in the globals while 'peter' is after.

The error message is just a little confusing to a Python newbie, I
think.

Thanks again!

- Baoqiu
 

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

Forum statistics

Threads
473,981
Messages
2,570,188
Members
46,732
Latest member
ArronPalin

Latest Threads

Top