我保留了一个事务缓存,以便在水印或对象完成事件时刷新(到持久存储)。由于__del__
在每个对象上都是no longer guaranteed to be called,因此将相似函数(或__del__
本身)挂钩到atexit.register
(初始化期间)是否合适?
如果我没弄错的话,这个将导致该方法绑定的对象挂起,直到程序终止。这不太可能是一个问题,但也许有一个更优雅的解决方案?
注意:我知道使用__del__
是不理想的,因为it can cause uncatchable exceptions,但我想不出另一种方法来做到这一点,因为我一直在通过我的级联finalize()
级联调用程序。 TIA!
答案 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
是前往这里的方式。