【问题标题】:Save state in file on cleanup using __del__?在使用 __del__ 进行清理时将状态保存在文件中?
【发布时间】:2011-06-24 22:31:14
【问题描述】:

我有一个如下所示的课程:

class A:
    def __init__(self, filename, sources):
        # gather info from file
        # info is updated during lifetime of the object

    def close(self):
        # save info back to file

现在,这是在一个服务器程序中,因此它可能会在没有事先通知的情况下被信号关闭。如果可能的话,定义它以确保类保存它的信息是否安全?

def __del__(self):
    self.close()

如果不是,您会建议什么作为解决方案?

【问题讨论】:

  • 不要使用 'del' 来处理这种事情。它不能保证在你的进程运行的生命周期内被调用,甚至在退出时也不被调用。

标签: python del resource-cleanup


【解决方案1】:

等到以后不是让事情变得可靠的策略。事实上,你必须走完全相反的方向。一旦你知道应该持久化的东西,你就需要采取行动来持久化它。事实上,如果您想使其可靠,您需要首先将在您尝试提交更改时可能发生的从故障中恢复所需的步骤写入磁盘。伪python:

class A:
    def __init__(self, filename, sources):
        self.recover()
        # gather info from file
        # info is updated during lifetime of the object

    def update_info(self, info):
        # append 'info' to recovery_log
        # recovery_log.flush()
        # write 'info' to file
        # file.flush()
        # append 'info-SUCCESS' to recover_log
        # recovery_log.flush()

    def recover(self):
        # open recovery_log
        # skip to last 'info-SUCCESS'
        # read 'info' from recover_log
        # write 'info' to file
        # file.flush()
        # append 'info-SUCCESS' to recover_log
        # recovery_log.flush()

重要的一点是recover() 每次都会发生,并且每个步骤后面都有一个flush() 以确保数据在下一步发生之前将其输出到磁盘。另一个重要的事情是,恢复日志本身只会发生附加。不会以任何方式覆盖日志中的数据会损坏。

【讨论】:

    【解决方案2】:

    没有。你是永远安全的。

    如果操作系统想在没有事先通知的情况下杀死你,它会的。你对此无能为力。您的程序可以在任何指令之后随时停止运行,并且没有机会执行任何额外的代码。

    没有办法保护您的服务器免受终止信号的影响。

    如果需要,您可以捕获较小的信号并手动删除您的对象,从而强制调用close()

    【讨论】:

    • 我知道我永远不会安全。如果可能的话,我想知道如何自动清理。
    • 您可以使用退出挂钩。请参阅基思的回答。
    【解决方案3】:

    为了有序清理,您可以使用sys.atexit 挂钩。在那里注册一个调用您的 close 方法的函数。 on object 的析构函数不能在exit时调用。

    【讨论】:

    • 我建议不要使用 atexit。你最好设计一个可预测的退出/清理路径。
    • 没错,在这种情况下,最好不要将未保存的信息保留太久,并使用上下文管理器。但是 atexit 可以帮助将已经不太好的设计调整为更安全的东西。
    【解决方案4】:

    __del__ 方法是 not guaranteed,用于解释器退出时仍然存在的对象。

    即使调用__del__,也可能调用得太晚。特别是,它可能发生在它要调用的模块已被卸载之后。正如 Keith 所指出的,sys.atexit 更安全。

    【讨论】:

    • 我认为这不可能发生。当调用 __del__ 方法时,它仍然引用导入到其作用域中的任何模块以及从 self 引用的任何对象,因此它们还不能被清理。如有必要,Python 将忽略对__del__ 的调用,而不是乱序运行。
    • 文档说:“不能保证 __del__() 方法在解释器退出时仍然存在的对象被调用”
    猜你喜欢
    • 2016-05-31
    • 1970-01-01
    • 2023-03-27
    • 2013-12-18
    • 1970-01-01
    • 1970-01-01
    • 2020-01-05
    • 1970-01-01
    • 2021-04-26
    相关资源
    最近更新 更多