3

我保留事务缓存以在水印或对象完成的事件中刷新(到持久存储)。由于不再保证在每个对象上都被调用,因此将类似函数(或自身)挂接到(在初始化期间)的适当方法__del__是什么?__del__atexit.register

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

注意:我知道 using__del__是不理想的,因为它可能会导致无法捕获的异常,但我想不出另一种方法来做这件事,除非finalize()在我的程序中一直进行级联调用。蒂亚!

4

5 回答 5

4

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

于 2008-12-23T05:10:35.403 回答
3

我会说atexit或尝试看看您是否可以将代码重构为能够使用默认情况下在 2.5 和 2.6with_statement中的a 来表示。__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:
  ...

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

于 2008-12-23T14:21:43.777 回答
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
于 2008-12-23T10:46:14.743 回答
2

如果您在执行刷新时不需要对象处于活动状态,则可以使用弱引用

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

如果需要保证在某个时间点完成,您可以遍历终止时的弱引用列表以手动刷新任何仍然活着的引用。

于 2008-12-23T21:52:16.927 回答
0

我认为这atexit是去这里的方式。

于 2008-12-23T06:51:34.653 回答