Python:通过终结器在程序终止之前刷新缓冲区

时间:2008-12-23 04:15:05

标签: python buffer destructor finalizer

我保留了一个事务缓存,以便在水印或对象完成事件时刷新(到持久存储)。由于__del__在每个对象上都是no longer guaranteed to be called,因此将相似函数(或__del__本身)挂钩到atexit.register(初始化期间)是否合适?

如果我没弄错的话,这个导致该方法绑定的对象挂起,直到程序终止。这不太可能是一个问题,但也许有一个更优雅的解决方案?

注意:我知道使用__del__是不理想的,因为it can cause uncatchable exceptions,但我想不出另一种方法来做到这一点,因为我一直在通过我的级联finalize()级联调用程序。 TIA!

5 个答案:

答案 0 :(得分:4)

如果必须处理资源,首选方法是明确调用close()finalize()方法。看一下with语句来抽象它。在您的情况下,weakref模块可能是一个选项。缓存的对象可以由系统进行垃圾收集,并调用它们的__del__()方法,或者如果它们仍然存活则最终确定它们。

答案 1 :(得分:3)

我会说atexit或尝试看看你是否可以重构代码,使其能够使用with_statement表示,该__future__在2.5和2.6中的@contextlib.contextmanager def start_transaction(db): db.start() yield db.end() with start_transaction(db) as transaction: ... 中默认。 2.5包含一个模块contextlib来简化一些事情。当使用Canonical的Storm ORM时,我做过类似的事情。

来自将来导入with_statement

{{1}}

对于非db情况,您可以只注册要使用全局刷新的对象,然后使用类似的东西。这种方法的好处是它可以使事情明确。

答案 2 :(得分: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

答案 3 :(得分:2)

如果您在执行同花时不需要对象存活,可以使用weak references

这与您提出的解决方案类似,但不是使用实际引用,而是存储弱引用列表,并使用回调函数执行刷新。这样,引用不会使这些对象保持活动状态,并且您不会遇到使用__del__方法的任何循环垃圾问题。

如果需要保证在某个点完成,你可以在终止时运行弱引用列表来手动清除任何仍然活着的。

答案 4 :(得分:0)

我认为atexit是前往这里的方式。