2008-12-23 60 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: 
    ... 

对于非分贝的情况下,你可以只注册到与全球冲洗的对象,然后使用类似的东西。这种方法的好处是它使事情明确。