Does python hate cathy?

Discussion in 'Python' started by QS, Mar 24, 2008.

  1. QS

    QS Guest

    Hi to all!
    I am new to python, and I encountered a weird problem.

    Here is my code

    ##########>8####################
    #!/usr/bin/python
    # Filename: objvar.py
    class Person:
    '''Represents a person.'''

    population = 0
    #sex = 'F'
    #age = 22
    # It is vague here: is this variable going to be a class, or
    object, variable

    def __init__(self, name, sex):
    '''Initializes the person's data.'''
    self.name = name
    self.sex = sex
    print '(Initializing %s )' % self.name
    # When this person is created, he/she
    # adds to the population
    Person.population += 1

    def __del__(self):
    '''I am dying.'''

    print '%s says bye.' % self.name
    Person.population -= 1
    if Person.population == 0:
    print 'I am the last one.'
    else:
    print 'There are still %d people left.' %
    Person.population

    def sayHi(self):
    '''Greeting by the person.

    Really, that's all it does.'''

    self.age = 25
    print 'Hi, my name is %s, and I am %s, and I am age %d ' %
    (self.name, self.sex, self.age)

    def howMany(self):
    '''Prints the current population.'''
    if Person.population == 1:
    print 'I am the only person here.'
    else:
    print 'We have %d persons here.' % Person.population

    swaroop = Person('Swaroop', 'M')
    swaroop.sayHi()
    swaroop.howMany()
    kalam = Person('Abdul Kalam', 'M')
    kalam.sayHi()
    kalam.howMany()
    cathy = Person('Catherine', 'F')
    cathy.sayHi()
    cathy.howMany()
    swaroop.sayHi()
    swaroop.howMany()


    ############# 8< #########################


    When I run this script, I got the following exception:
    Exception exceptions.AttributeError: "'NoneType' object has no
    attribute 'population'" in <bound method Person.__del__ of
    <__main__.Person instance at 0xb7d8ac6c>> ignored

    To to newcomer like me, this message doesn't make much sense. What
    seems weird to me is that, if I change the variable cathy to something
    else, like cath, or even cat, then the script will finish gracefully.
    Why "cathy" is not liked?!!

    Some of you may have recognized that the code is derived from a sample
    code in Swaroop's "A byte of python".

    My python is of version 2.5.1, on Ubuntu.
     
    QS, Mar 24, 2008
    #1
    1. Advertising

  2. On Mar 23, 8:01 pm, QS <> wrote:
    > Hi to all!
    > I am new to python, and I encountered a weird problem.
    >
    > Here is my code
    >
    > ##########>8####################
    > #!/usr/bin/python
    > # Filename: objvar.py
    > class Person:
    > '''Represents a person.'''
    >
    > population = 0
    > #sex = 'F'
    > #age = 22
    > # It is vague here: is this variable going to be a class, or
    > object, variable
    >
    > def __init__(self, name, sex):
    > '''Initializes the person's data.'''
    > self.name = name
    > self.sex = sex
    > print '(Initializing %s )' % self.name
    > # When this person is created, he/she
    > # adds to the population
    > Person.population += 1
    >
    > def __del__(self):
    > '''I am dying.'''
    >
    > print '%s says bye.' % self.name
    > Person.population -= 1
    > if Person.population == 0:
    > print 'I am the last one.'
    > else:
    > print 'There are still %d people left.' %
    > Person.population
    >
    > def sayHi(self):
    > '''Greeting by the person.
    >
    > Really, that's all it does.'''
    >
    > self.age = 25
    > print 'Hi, my name is %s, and I am %s, and I am age %d ' %
    > (self.name, self.sex, self.age)
    >
    > def howMany(self):
    > '''Prints the current population.'''
    > if Person.population == 1:
    > print 'I am the only person here.'
    > else:
    > print 'We have %d persons here.' % Person.population
    >
    > swaroop = Person('Swaroop', 'M')
    > swaroop.sayHi()
    > swaroop.howMany()
    > kalam = Person('Abdul Kalam', 'M')
    > kalam.sayHi()
    > kalam.howMany()
    > cathy = Person('Catherine', 'F')
    > cathy.sayHi()
    > cathy.howMany()
    > swaroop.sayHi()
    > swaroop.howMany()
    >
    > ############# 8< #########################
    >
    > When I run this script, I got the following exception:
    > Exception exceptions.AttributeError: "'NoneType' object has no
    > attribute 'population'" in <bound method Person.__del__ of
    > <__main__.Person instance at 0xb7d8ac6c>> ignored
    >
    > To to newcomer like me, this message doesn't make much sense. What
    > seems weird to me is that, if I change the variable cathy to something
    > else, like cath, or even cat, then the script will finish gracefully.
    > Why "cathy" is not liked?!!
    >
    > Some of you may have recognized that the code is derived from a sample
    > code in Swaroop's "A byte of python".
    >
    > My python is of version 2.5.1, on Ubuntu.


    That's really weird... it's reproducible on Windows too. It doesn't
    make any sense why the name of the variable would make a difference.
    My guess is you hit some kind of obscure bug.

    George
     
    George Sakkis, Mar 24, 2008
    #2
    1. Advertising

  3. QS

    John Machin Guest

    On Mar 24, 11:42 am, George Sakkis <> wrote:
    > On Mar 23, 8:01 pm, QS <> wrote:
    >
    >
    >
    > > Hi to all!
    > > I am new to python, and I encountered a weird problem.

    >
    > > Here is my code

    >
    > > ##########>8####################
    > > #!/usr/bin/python
    > > # Filename: objvar.py
    > > class Person:
    > > '''Represents a person.'''

    >
    > > population = 0
    > > #sex = 'F'
    > > #age = 22
    > > # It is vague here: is this variable going to be a class, or
    > > object, variable

    >
    > > def __init__(self, name, sex):
    > > '''Initializes the person's data.'''
    > > self.name = name
    > > self.sex = sex
    > > print '(Initializing %s )' % self.name
    > > # When this person is created, he/she
    > > # adds to the population
    > > Person.population += 1

    >
    > > def __del__(self):
    > > '''I am dying.'''

    >
    > > print '%s says bye.' % self.name
    > > Person.population -= 1
    > > if Person.population == 0:
    > > print 'I am the last one.'
    > > else:
    > > print 'There are still %d people left.' %
    > > Person.population

    >
    > > def sayHi(self):
    > > '''Greeting by the person.

    >
    > > Really, that's all it does.'''

    >
    > > self.age = 25
    > > print 'Hi, my name is %s, and I am %s, and I am age %d ' %
    > > (self.name, self.sex, self.age)

    >
    > > def howMany(self):
    > > '''Prints the current population.'''
    > > if Person.population == 1:
    > > print 'I am the only person here.'
    > > else:
    > > print 'We have %d persons here.' % Person.population

    >
    > > swaroop = Person('Swaroop', 'M')
    > > swaroop.sayHi()
    > > swaroop.howMany()
    > > kalam = Person('Abdul Kalam', 'M')
    > > kalam.sayHi()
    > > kalam.howMany()
    > > cathy = Person('Catherine', 'F')
    > > cathy.sayHi()
    > > cathy.howMany()
    > > swaroop.sayHi()
    > > swaroop.howMany()

    >
    > > ############# 8< #########################

    >
    > > When I run this script, I got the following exception:
    > > Exception exceptions.AttributeError: "'NoneType' object has no
    > > attribute 'population'" in <bound method Person.__del__ of
    > > <__main__.Person instance at 0xb7d8ac6c>> ignored

    >
    > > To to newcomer like me, this message doesn't make much sense. What
    > > seems weird to me is that, if I change the variable cathy to something
    > > else, like cath, or even cat, then the script will finish gracefully.
    > > Why "cathy" is not liked?!!

    >
    > > Some of you may have recognized that the code is derived from a sample
    > > code in Swaroop's "A byte of python".

    >
    > > My python is of version 2.5.1, on Ubuntu.

    >
    > That's really weird... it's reproducible on Windows too. It doesn't
    > make any sense why the name of the variable would make a difference.
    > My guess is you hit some kind of obscure bug.
    >


    My guess after reading the manual:
    """
    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.
    """
    is that farnarkeling about in a __del__ method is *not* a good idea.
     
    John Machin, Mar 24, 2008
    #3
  4. On Sun, 2008-03-23 at 17:42 -0700, George Sakkis wrote:
    > That's really weird... it's reproducible on Windows too. It doesn't
    > make any sense why the name of the variable would make a difference.
    > My guess is you hit some kind of obscure bug.


    This is not a bug, just an unexpected feature:
    http://mail.python.org/pipermail/python-list/2005-January/304873.html

    What's happening is that at the end of the script, all objects in the
    global namespace are set to None (in order to decrease their reference
    count and trigger garbage collection). This happens in the order in
    which the names appear as keys in the globals dictionary. It randomly
    happens that "swaroop", "kalam", and "cath" all are hashed in front of
    "Person", but "cathy" is hashed after "Person".

    Hence, if Catherine is named cath, Python "None's" all the instances
    first and then the type last, and all is well. However, if Catherine is
    called cathy, Person is set to None before cathy. Then, in the lookup of
    the global name "Person" during cathy.__del__, Person is None, which
    doesn't have a "population" attribute, causing the AttributeError.

    Possible workarounds are:
    1) Explicitly delete the global names for the instances before the
    script runs out.
    2) Don't refer to the "Person" type by its global name in __del__, but
    indirectly as type(self). (This requires Person to be a new-style class,
    though.)

    --
    Carsten Haese
    http://informixdb.sourceforge.net
     
    Carsten Haese, Mar 24, 2008
    #4
  5. QS

    Tim Chase Guest

    > When I run this script, I got the following exception:
    > Exception exceptions.AttributeError: "'NoneType' object has no
    > attribute 'population'" in <bound method Person.__del__ of
    > <__main__.Person instance at 0xb7d8ac6c>> ignored
    >
    > To to newcomer like me, this message doesn't make much sense. What
    > seems weird to me is that, if I change the variable cathy to something
    > else, like cath, or even cat, then the script will finish gracefully.
    > Why "cathy" is not liked?!!
    >
    > My python is of version 2.5.1, on Ubuntu.


    When I first read this, I thought you were crazy. I ran the
    code, and you're not. I tried under versions 2.3, 2.4, and 2.5
    on my Debian box, and got the same results. Neither "cathy" nor
    "ca" works, but "c", "cat", "cath", "cath_y" and "cathy_" all
    work just fine.

    Even more infuriating is that if I try and use pdb to debug,
    Swaroop drops into pdb, but Abdul and Cathy both error out.

    That's just plain nuts. Something odd is happening with __del__
    calls.

    -tkc
     
    Tim Chase, Mar 24, 2008
    #5
  6. QS

    QS Guest

    Thanks to you all! It's good to know...

    On Mar 23, 9:02 pm, Carsten Haese <> wrote:
    > On Sun, 2008-03-23 at 17:42 -0700, George Sakkis wrote:
    > > That's really weird... it's reproducible on Windows too. It doesn't
    > > make any sense why the name of the variable would make a difference.
    > > My guess is you hit some kind of obscure bug.

    >
    > This is not a bug, just an unexpected feature:http://mail.python.org/pipermail/python-list/2005-January/304873.html
    >
    > What's happening is that at the end of the script, all objects in the
    > global namespace are set to None (in order to decrease their reference
    > count and trigger garbage collection). This happens in the order in
    > which the names appear as keys in the globals dictionary. It randomly
    > happens that "swaroop", "kalam", and "cath" all are hashed in front of
    > "Person", but "cathy" is hashed after "Person".
    >
    > Hence, if Catherine is named cath, Python "None's" all the instances
    > first and then the type last, and all is well. However, if Catherine is
    > called cathy, Person is set to None before cathy. Then, in the lookup of
    > the global name "Person" during cathy.__del__, Person is None, which
    > doesn't have a "population" attribute, causing the AttributeError.
    >
    > Possible workarounds are:
    > 1) Explicitly delete the global names for the instances before the
    > script runs out.
    > 2) Don't refer to the "Person" type by its global name in __del__, but
    > indirectly as type(self). (This requires Person to be a new-style class,
    > though.)
    >
    > --
    > Carsten Haesehttp://informixdb.sourceforge.net
     
    QS, Mar 24, 2008
    #6
  7. On Sun, 2008-03-23 at 20:05 -0500, Michael Wieher wrote:
    > is that farnarkeling about in a __del__ method is *not* a good
    > idea.
    >
    > Ok that having been said, is accessing an unbound variable of a class
    > and using it to coordinate between instances of that class common
    > practice?


    I'm not sure what you mean by "accessing an unbound variable" means in
    the context of this thread, or any context for that matter. Nothing of
    the kind is happening in the OP's example. What's happening is that a
    class attribute is initialized, incremented, and decremented. Using
    class attributes is common practice.

    The problem, as I explained in my previous post, is that the class
    attribute is looked up via a global name of the class, and that name may
    or may not have disappeared in a puff of logic by the time the
    instance's __del__ method is run in the VM shutdown sequence.

    --
    Carsten Haese
    http://informixdb.sourceforge.net
     
    Carsten Haese, Mar 24, 2008
    #7
  8. On Mon, 2008-03-24 at 02:18 +0100, I wrote the barely intelligible
    phrase:
    > I'm not sure what you mean by "accessing an unbound variable" means in
    > the context of this thread


    I'm starting to sound like castironpi. Time to go to sleep.

    --
    Carsten Haese
    http://informixdb.sourceforge.net
     
    Carsten Haese, Mar 24, 2008
    #8
  9. On Mar 23, 9:02 pm, Carsten Haese <> wrote:

    > On Sun, 2008-03-23 at 17:42 -0700, George Sakkis wrote:
    > > That's really weird... it's reproducible on Windows too. It doesn't
    > > make any sense why the name of the variable would make a difference.
    > > My guess is you hit some kind of obscure bug.

    >
    > This is not a bug, just an unexpected feature:http://mail.python.org/pipermail/python-list/2005-January/304873.html


    That would make a great entry for the Python IAQ [1] ! As they say,
    you learn something new every day :)

    George

    [1] http://norvig.com/python-iaq.html
     
    George Sakkis, Mar 24, 2008
    #9
  10. QS

    Terry Reedy Guest

    "QS" <> wrote in message
    news:...

    >From the title, I assumed this was spam like others with similar titles --

    and that the perl newsgroup, for instance, would have 'Does perl hate
    cathy?

    | I am new to python, and I encountered a weird problem.

    Observation: as you will learn, the form of the error message was different
    from the standard tracebacks one gets during program execution. This was a
    clue that it was a cleanup message and actually did make sense.

    Summary lessons.

    1. What a Python interpreter does after it executes the last statement is
    undefined by the language spec. It could do absolutely nothing (and I wish
    some programs that wastefully spend minutes 'cleaning up' did just that!).
    CPython tries to do some cleanup when requested but the results are
    sometimes seemingly arbitrary.

    2. If you use __del__, do so for a reason (and keeping a population count
    is one, though rare*), and explicitly delete the objects for which you want
    dependable behavior.

    *A population count is a good example of a class attribute. But it seems
    to be rare in practice because if one wants that, it seems that a
    population collection (with a len() method) is usually also wanted --
    perhaps so one can iterate thru the population.

    3. Experimenting with Python is a good way to learn. Keep it up!

    tjr
     
    Terry Reedy, Mar 24, 2008
    #10
  11. Interestingly, if you change

    swaroop = Person('Swaroop', 'M')
    swaroop.sayHi()
    swaroop.howMany()
    kalam = Person('Abdul Kalam', 'M')
    kalam.sayHi()
    kalam.howMany()
    cathy = Person('Catherine', 'F')
    cathy.sayHi()
    cathy.howMany()
    swaroop.sayHi()
    swaroop.howMany()

    to

    def main():
    swaroop = Person('Swaroop', 'M')
    swaroop.sayHi()
    swaroop.howMany()
    kalam = Person('Abdul Kalam', 'M')
    kalam.sayHi()
    kalam.howMany()
    cathy = Person('Catherine', 'F')
    cathy.sayHi()
    cathy.howMany()
    swaroop.sayHi()
    swaroop.howMany()
    return 0


    if __name__ == "__main__":
    sys.exit(main())


    The problem goes away. (This is a good coding practice in any event.)

    As others have pointed out, the order in which local variables are deleted
    is undefined. It looks to me as if the class Person got deleted before
    Catherine did.

    Adding

    del kalam
    del cathy
    del swaroop

    to the end of the program did fix the problem, presumably by forcing
    kalam, cathy, and swaroop from being deleted before Person.

    However, Adding

    self.myclass = Person

    to the __init__() method didn't stop the problem. I thought it might, because
    then each of the objects would have held a reference to Person. Actually, I would
    have thought they'd hold a reference by merely existing, so is this not a bug?

    --
    -Ed Falk,
    http://thespamdiaries.blogspot.com/
     
    Edward A. Falk, Mar 25, 2008
    #11
  12. En Tue, 25 Mar 2008 02:09:58 -0300, Edward A. Falk <>
    escribió:

    > However, Adding
    >
    > self.myclass = Person
    >
    > to the __init__() method didn't stop the problem. I thought it might,
    > because
    > then each of the objects would have held a reference to Person.
    > Actually, I would
    > have thought they'd hold a reference by merely existing, so is this not
    > a bug?


    Yes, they already have a reference (self.__class__). The problem is that
    __del__ references Person by *name*, and that name is reset to None (like
    all other module globals) as part of the interpreter shutdown sequence.
    Using self.__class__ would avoid this particular bug, but in general, it's
    better not to rely on __del__ at all.

    See http://bugs.python.org/issue1513802 and
    http://bugs.python.org/issue1717900

    --
    Gabriel Genellina
     
    Gabriel Genellina, Mar 25, 2008
    #12
  13. It seems like this is mostly a non-issue. The original code actually
    works correctly (of course the updated versions that solve the
    exception problem are probably better). The only thing that is going
    haywire is the interpreter shutdown process. I think it is going a
    bit overboard to "consider __del__ harmful" because it might throw an
    exception as the program is quitting. It is important to not rely on
    __del__ too much but there can be some designs where you need to know
    when something is gone, and you don't know exactly where or when
    something is deleted.

    Then again, I can count the number of times I have ever needed __del__
    with no fingers (never used it!). Still, quite interesting to
    explore.
     
    Patrick Mullen, Mar 25, 2008
    #13
  14. In article <>,
    Patrick Mullen <> wrote:

    >Then again, I can count the number of times I have ever needed __del__
    >with no fingers (never used it!). Still, quite interesting to
    >explore.


    I used it once, for an object that had a doubly-linked list.
    The __del__() method walked the list, setting all the elements'
    prev/next pointers to None to make sure the elements of the list would
    get garbage-collected.

    --
    -Ed Falk,
    http://thespamdiaries.blogspot.com/
     
    Edward A. Falk, Mar 25, 2008
    #14
  15. On Tue, 25 Mar 2008 14:58:51 +0000, Edward A. Falk wrote:

    > In article <>,
    > Patrick Mullen <> wrote:
    >
    >>Then again, I can count the number of times I have ever needed __del__
    >>with no fingers (never used it!). Still, quite interesting to
    >>explore.

    >
    > I used it once, for an object that had a doubly-linked list.
    > The __del__() method walked the list, setting all the elements'
    > prev/next pointers to None to make sure the elements of the list would
    > get garbage-collected.


    Without the `__del__()` the elements would get garbage collected just
    fine. If you don't want to wait until the garbage collector in CPython
    detects the cycle, you can use `weakref`\s for one of the two "pointers"
    in each element.

    Ciao,
    Marc 'BlackJack' Rintsch
     
    Marc 'BlackJack' Rintsch, Mar 25, 2008
    #15
  16. Marc 'BlackJack' Rintsch <> writes:

    > On Tue, 25 Mar 2008 14:58:51 +0000, Edward A. Falk wrote:
    >
    >> In article <>,
    >> Patrick Mullen <> wrote:
    >>
    >>>Then again, I can count the number of times I have ever needed __del__
    >>>with no fingers (never used it!). Still, quite interesting to
    >>>explore.

    >>
    >> I used it once, for an object that had a doubly-linked list.
    >> The __del__() method walked the list, setting all the elements'
    >> prev/next pointers to None to make sure the elements of the list would
    >> get garbage-collected.

    >
    > Without the `__del__()` the elements would get garbage collected just
    > fine.


    It gets even worse than that: the __del__ method actually *prevents*
    objects that participate in cycles from getting garbage-collected.
    Python's GC doesn't deallocate objects that define __del__. (The way
    to handle those is to grep for them in gc.garbage, break the cycles in
    a way that works for the application -- e.g. by removing the prev and
    next references -- and finally del gc.garbage[:].)
     
    Hrvoje Niksic, Mar 25, 2008
    #16
  17. QS

    Guest

    On Mar 23, 8:05 pm, Tim Chase <> wrote:
    > > When I run this script, I got the following exception:
    > > Exception exceptions.AttributeError: "'NoneType' object has no
    > > attribute 'population'" in <bound method Person.__del__ of
    > > <__main__.Person instance at 0xb7d8ac6c>> ignored

    >
    > > To to newcomer like me, this message doesn't make much sense. What
    > > seems weird to me is that, if I change the variable cathy to something
    > > else, like cath, or even cat, then the script will finish gracefully.
    > > Why "cathy" is not liked?!!

    >
    > > My python is of version 2.5.1, on Ubuntu.

    >
    > When I first read this, I thought you were crazy.  I ran the
    > code, and you're not.  I tried under versions 2.3, 2.4, and 2.5
    > on my Debian box, and got the same results.  Neither "cathy" nor
    > "ca" works,  but "c", "cat", "cath", "cath_y" and "cathy_" all
    > work just fine.
    >
    > Even more infuriating is that if I try and use pdb to debug,
    > Swaroop drops into pdb, but Abdul and Cathy both error out.
    > [snip]


    > Does Python hate Cathy?


    Does Pothon?
     
    , Mar 25, 2008
    #17
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Nicolas Matringe

    Why do we hate variables?

    Nicolas Matringe, Jan 22, 2004, in forum: VHDL
    Replies:
    4
    Views:
    4,210
    fabbl
    Jan 23, 2004
  2. Weng Tianxiang

    I hate VHDL!!!

    Weng Tianxiang, Jun 3, 2004, in forum: VHDL
    Replies:
    51
    Views:
    5,160
    roller
    Jun 19, 2004
  3. Jim Lewis

    Re: I hate VHDL!!!

    Jim Lewis, Jun 25, 2004, in forum: VHDL
    Replies:
    14
    Views:
    1,160
    Just an Illusion
    Jul 5, 2004
  4. Replies:
    5
    Views:
    478
    Neredbojias
    Oct 24, 2005
  5. Bill Kelly
    Replies:
    0
    Views:
    102
    Bill Kelly
    Mar 7, 2007
Loading...

Share This Page