[ python-Bugs-1545463 ] New-style classes fail to cleanup attributes

SourceForge.net noreply at sourceforge.net
Wed Aug 30 15:36:13 CEST 2006


Bugs item #1545463, was opened at 2006-08-23 14:24
Message generated for change (Comment added) made by jimjjewett
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1545463&group_id=5470

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: Python Interpreter Core
Group: Python 2.4
Status: Open
Resolution: None
Priority: 5
Submitted By: Alexander Belopolsky (belopolsky)
Assigned to: Nobody/Anonymous (nobody)
Summary: New-style classes fail to cleanup attributes

Initial Comment:
> cat x.py
class X(object):
    def __init__(self, x):
        self.x = x
        print 'creating X(%r)' % x

    def __del__(self):
        print 'deleting X(%r)' % self.x

class A(object):
    x = X('new')

class B:
    x = X('old')
> python x.py
creating X('new')
creating X('old')
deleting X('old')

Python 2.4.2 (#2, Jan 13 2006, 12:00:38)
Python 2.6a0 (trunk:51513M, Aug 23 2006, 14:17:11)

----------------------------------------------------------------------

Comment By: Jim Jewett (jimjjewett)
Date: 2006-08-30 09:36

Message:
Logged In: YES 
user_id=764593

I suggest changing status to Pending Close - not a bug.

----------------------------------------------------------------------

Comment By: Jim Jewett (jimjjewett)
Date: 2006-08-30 09:34

Message:
Logged In: YES 
user_id=764593

Looking at your example code (as best I can guess about 
indentation), it looks like

module x <==> class X
module x <==> class A ==> A's instance x ==> class X
module x <==> class B ==> B's instance x ==> class X

So the x instances can't go away until A and B do, which 
means at module cleanup.  But when the module cleans up, it 
may well clean up X before A, so that A.x no longer has an 
active class, so that it can't find its __del__ method.



----------------------------------------------------------------------

Comment By: Jim Jewett (jimjjewett)
Date: 2006-08-30 09:22

Message:
Logged In: YES 
user_id=764593

The funny interaction with modules is probably that the 
module retains a reference to the class (and vice versa), 
so the class can't go away until the module does -- and a 
module in sys.modules can't go away.

The __del__ methods are not called if the interpreter can't 
decide which to call first.  For example, if

    A.attr=B
    B.attr=A

then A and B form a cycle (like the class and its defining 
module).  If only one has a __del__ method, it gets called, 
but if both do, then python doesn't know which to call 
first, so it never calls either.

You may have a cycle like

module <==> class <==>instanceA
               \  <==>instanceB

So that it can't decide whether to take care of instanceA 
or instanceB first.

Or it might be that the __del__ methods actually are being 
called, but not until module teardown has begun, so they 
don't work right.


----------------------------------------------------------------------

Comment By: Alexander Belopolsky (belopolsky)
Date: 2006-08-23 20:08

Message:
Logged In: YES 
user_id=835142

I used __del__ just to illustrate the problem. In real life
application, X was a type defined in a C module and I've
noticed that it's tp_dealloc is not called on instances
assigned to class variables.

BTW, what are the circumstances when __del__() methods are
not called for objects that still exist when the interpreter
exits?

----------------------------------------------------------------------

Comment By: Georg Brandl (gbrandl)
Date: 2006-08-23 19:18

Message:
Logged In: YES 
user_id=849994

There's also this sentence in the __del__ docs:
"""
It is not guaranteed that __del__() methods are called for
objects that still exist when the interpreter exits.
"""

----------------------------------------------------------------------

Comment By: Alexander Belopolsky (belopolsky)
Date: 2006-08-23 18:54

Message:
Logged In: YES 
user_id=835142

Yes, I've found that (using gc.get_referrers!), but this
does not explain why A is not cleaned up when the program exits.

Note that if I put class A definition inside a function, it
does get cleaned up.  Must be some funny interation between
module and new-style class objects.

----------------------------------------------------------------------

Comment By: Georg Brandl (gbrandl)
Date: 2006-08-23 18:45

Message:
Logged In: YES 
user_id=849994

Note that new-style classes are always part of a reference
cycle (you can find this out via gc.get_referrers).
Therefore, they will not be deleted instantly, but only
after gc collects them (you can trigger that via gc.collect).

----------------------------------------------------------------------

Comment By: Alexander Belopolsky (belopolsky)
Date: 2006-08-23 18:01

Message:
Logged In: YES 
user_id=835142

It looks like the class object is not deleted alltogether:



class X(object):
    def __init__(self, x):
        self.x = x
        print 'creating X(%r)' % x

    def __del__(self):
        print 'deleting X(%r)' % self.x
        
class A(object):
    x = X('new')

del A

Output:
creating X('new')
deleting X('new')



----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=105470&aid=1545463&group_id=5470


More information about the Python-bugs-list mailing list