2010-05-25 109 views
3

语境基类蟒蛇__del__处理

我知道,如果我问一个关于Python析构函数的问题,标准参数将是使用环境,而不是在子类之前被删除。让我首先解释为什么我不这样做。

我正在写一个logging.Handler的子类。当一个实例关闭时,它将一个标记值发送到Queue.Queue。如果没有,第二个线程将永远运行,等待Queue.Queue.get()完成。

我正在写这个与其他开发人员的想法,所以我不想失败的处理程序对象调用close()导致程序挂起。

因此,我在__del __()中添加了一个检查以确保该对象正确关闭。

我了解循环引用可能会导致它在某些情况下失败。对此我没有太多的办法。

问题

下面是一些简单的示例代码:

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" 

当我运行此我得到的,如预期:

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

如果我在设定explicit_deleteFalse第一行,我得到:

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 

在调用x.__del__()之前似乎删除了Base的定义。

关于__del __()的Python文档警告说,子类需要调用基类以获得干净的删除,但在这里看起来是不可能的。

你能看到我在哪里做出了糟糕的一步吗?

回答

1

一个解决方案,工作,但可能不是最好的:

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" 

如果你保持第二参考基类

2

你的代码是有些误导,我尝试过了,它只是失败如你所述。但后来我写了这样的事情:

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() 

输出功率为:

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

所以我猜你不能依靠翻译关闭(我认为实例之前,该类的对象被收集在__del__的方法呢? ),但在此之前,他们的工作和预期一致。

也许保持主线程活着,直到其他人死了,而不是在主线程中创建你的Handler子类实例就足够了?

+0

这非常有趣。在我的* real *代码中,它不是解释器关闭,只是线程关闭,因为另一个线程仍在运行,直到它被告知关闭。我明白,当解释器关闭时,不能保证会调用__del __()函数 - 这很好,因为我所要做的就是删除足够的引用来触发解释器关闭。 – Oddthinking 2010-05-25 10:48:40