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

发布于 2024-07-10 21:41:32 字数 598 浏览 6 评论 0原文

我保留了一个事务缓存,以便在发生水印或对象终结时刷新(到持久存储)。 由于 __del__不再保证在每个对象上调用,是将类似函数(或 __del__ 本身)挂接到 atexit.register (在初始化期间)的适当方法吗?

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

注意:我知道使用 __del__ 并不理想,因为 它可能会导致无法捕获的异常,但我想不出另一种方法可以在我的程序中完成如此短的级联 finalize() 调用。 蒂亚!

I keep a cache of transactions to flush (to persistent storage) on the event of a watermark or object finalization. Since __del__ is no longer guaranteed to be called on every object, is the appropriate approach to hook a similar function (or __del__ itself) into atexit.register (during initialization)?

If I'm not mistaken, this will cause the object to which the method is bound to hang around until program termination. This isn't likely to be a problem, but maybe there's a more elegant solution?

Note: I know using __del__ is non-ideal because it can cause uncatchable exceptions, but I can't think of another way to do this short of cascading finalize() calls all the way through my program. TIA!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

晚风撩人 2024-07-17 21:41:32

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

If you have to handle ressources the prefered way is to have an explicit call to a close() or finalize() method. Have a look at the with statement to abstract that. In your case the weakref module might be an option. The cached object can be garbage collected by the system and have their __del__() method called or you finalize them if they are still alive.

看轻我的陪伴 2024-07-17 21:41:32

我会说 atexit 或尝试看看是否可以将代码重构为能够使用 with_statement 来表达,该语句位于 __future__ 中默认为 2.5 和 2.6。 2.5 包含一个 contextlib 模块来简化一些事情。 我在使用 Canonical 的 Storm ORM 时做过类似的事情。

from future import with_statement

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

with start_transaction(db) as transaction:
  ...

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

I would say atexit or try and see if you can refactor the code into being able to be expressed using a with_statement which is in the __future__ in 2.5 and in 2.6 by default. 2.5 includes a module contextlib to simplify things a bit. I've done something like this when using Canonical's Storm ORM.

from future import with_statement

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

with start_transaction(db) as transaction:
  ...

For a non-db case, you could just register the objects to be flushed with a global and then use something similar. The benefit of this approach is that it keeps things explicit.

╭ゆ眷念 2024-07-17 21:41:32

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

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

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

If you don't need your object to be alive at the time you perform the flush, you could use weak references

This is similar to your proposed solution, but rather than using a real reference, store a list of weak references, with a callback function to perform the flush. This way, the references aren't going to keep those objects alive, and you won't run into any circular garbage problems with __del__ methods.

You can run through the list of weak references on termination to manually flush any still alive if this needs to be guaranteed done at a certain point.

黑白记忆 2024-07-17 21:41:32

将以下内容放入名为 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

Put the following in a file called destructor.py

import atexit

objects = []

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

atexit.register(_destructor)

now use it this way:

import destructor

class MyObj(object):
    def __init__(self):
        destructor.objects.append(self)
        # ... other init stuff
    def destroy(self):
        # clean up resources here
陌上青苔 2024-07-17 21:41:32

我认为 atexit 是解决这个问题的方法。

I think atexit is the way to go here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文