2008-12-23 58 views
3

我保留一個事務的緩存以在水印或對象最終化事件發生時刷新(持久存儲)。由於每個對象上的__del__no longer guaranteed to be called,因此將類似函數(或__del__本身)掛接到atexit.register(在初始化期間)是否合適?Python:在程序終止之前通過終結器刷新緩衝區

如果我沒有弄錯,這個導致該方法綁定的對象掛起,直到程序終止。這不可能是一個問題,但也許有一個更優雅的解決方案?

注:我知道使用__del__是不理想的,因爲it can cause uncatchable exceptions,但我想不出另一種方式做到這短短的級聯finalize()調用都通過我的程序一路的。 TIA!

回答

2

如果你不需要你的目標是在你執行刷新的時候還活着,你可以使用weak references

這類似於你提出的解決方案,而不是使用一個真正的參考,存儲列表弱引用,用回調函數執行刷新。這樣,引用不會使這些對象保持活動狀態,並且您將不會遇到與__del__方法有關的任何循環垃圾問題。

如果需要在某個點保證完成,您可以在終止時運行弱引用列表以手動刷新任何仍處於活動狀態的內容。

4

如果您必須處理資源,首選的方法是明確調用close()finalize()方法。看看with聲明來抽象。在你的情況下,weakref模塊可能是一個選項。緩存的對象可以被系統垃圾收集,並調用__del__()方法,或者如果它們仍處於活動狀態,則會將它們最終確定。

+0

您在布賴恩之前給出瞭解決方案,但他在一個更詳細的解釋中讓它點擊了我的大腦。對不起 - 我仍然贊成你的! – cdleary 2008-12-23 23:38:05

0

我認爲atexit是去這裏的路。

2

將下面的一個名爲destructor.py

import atexit 

objects = [] 

def _destructor(): 
    global objects 
    for obj in objects: 
     obj.destroy() 
    del objects 

atexit.register(_destructor) 

現在使用這種方式的文件:

import destructor 

class MyObj(object): 
    def __init__(self): 
     destructor.objects.append(self) 
     # ... other init stuff 
    def destroy(self): 
     # clean up resources here 
+0

模塊很酷,但我會爲可調用類而不是全局模塊投票。 – 2008-12-23 12:13:37

+0

@ S.洛特:可玩的不是單身。模塊對象是。這樣我可以有很多模塊使用一個析構函數模塊。 – nosklo 2009-01-08 13:48:40

3

我要說atexit或嘗試,看看您是否可以重構代碼到能夠可以用with_statement表示,其默認值爲2.5和2.6中的__future__。 2.5包含一個模塊contextlib來簡化一些事情。使用Canonical的Storm ORM時,我做了這樣的事情。

未來進口with_statement

@contextlib.contextmanager 
def start_transaction(db): 
    db.start() 
    yield 
    db.end() 

with start_transaction(db) as transaction: 
    ... 

對於非分貝的情況下,你可以只註冊到與全球沖洗的對象,然後使用類似的東西。這種方法的好處是它使事情明確。