The base class is removed before the subclass during python __del__ processing

Context

I know that if I ask a question about Python destructors, the use of contexts will be the standard argument. Let me begin by explaining why I do not.

I am writing a subclass to logging.Handler. When the instance is closed, it sends the sentinel value to the Queue.Queue queue. If this does not happen, the second thread will be left forever, waiting for Queue.Queue.get () to complete.

I write this with other developers, so I don’t want the call to call () not to be called by the handler object to cause the program to hang.

Therefore, I am adding the __del __ () check to ensure that the object has been closed properly.

I understand that circular links can lead to its failure in some circumstances. I can not do it.

Problem

Here is a simple code example:

explicit_delete = True

class Base:
    def __del__(self):
        print "Base class cleaning up."

class Sub(Base):
    def __del__(self):
        print "Sub-class cleaning up."
        Base.__del__(self)

x = Sub()

if explicit_delete:
    del x

print "End of thread"

When I run this, I get, as expected:

Sub-class cleaning up.
Base class cleaning up.
End of thread

If I set explicit_deletein Falsethe first line, I get:

End of thread
Sub-class cleaning up.
Exception AttributeError: "'NoneType' object has no attribute '__del__'" in <bound method Sub.__del__ of <__main__.Sub instance at 0x00F0B698>> ignored

The Base definition seems to be removed before the call x.__del__().

The Python documentation on __del __ () warns that the subclass must call the base class in order to get a clean delete, but this seems impossible here.

Do you see where I took a bad step?

+3
source share
2 answers

Your code is a bit misleading, I tried it and it failed as you described. But then I wrote something like this:

import threading

class Base( object ):
    def __del__(self):
        print "Base class cleaning up."

class Sub(Base):
    def __del__(self):
        print "Sub-class cleaning up."
        Base.__del__( self )

def f():
    x = Sub()
    print "End of thread"

t = threading.Thread( target = f )
t.start()
t.join()

and output:

End of thread
Sub-class cleaning up.
Base class cleaning up.
End of main thread.

, , __del__ ( , ?), , .

, , Handler ?

+2

, , :

explicit_delete = False

class Base(object):
    def __del__(self):
        print "Base class cleaning up."

class Sub(Base):
    base = Base
    def __init__(self):
        print 'stating'

    def __del__(self):
        print "Sub-class cleaning up."
        self.base.__del__(self)

x = Sub()
if explicit_delete:
    del x

print "End of thread"

+1

Source: https://habr.com/ru/post/1746963/


All Articles