2010-05-25 149 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