Python析构函数未被调用

7

有没有什么办法在对象销毁时调用我的析构函数?

def __del__(self):
    os.unlink(self.pidfile)

场景:有一个在运行进程的守护进程。当守护进程收到 SIGTERM 信号时,会立即将该信号发送给进程。此时进程会停止执行且不会调用 __del__ 方法。


那个已停止的进程还有引用吗? - Patrick Haugh
5
无法保证运行终结器。使用“with”语句,而非__del__()。然后设置一个SIGTERM的信号处理程序,该处理程序会引发异常,with语句可以做出响应。 - Kevin
2
@Kevin:Finalizers并不保证一定会运行,但我们实际上有更多的问题,因为当Python收到SIGTERM信号时,上下文管理器__exit__finally块默认情况下也不会运行。 - user2357112
1个回答

5
如评论中所述,为您的对象定义一个__exit__方法并使用with语句是“析构”对象的首选方式。这样更加明确和可预测。
但是,即使使用with语句,如果收到SIGTERM信号,也不能保证完全销毁您的对象。为了在接收到信号时执行某些操作,您需要添加信号处理程序。
import signal
import sys

def handle_signal(signum, frame):
    print('Got signal')
    #  Do some cleanup
    sys.exit(signum)  # Maybe ???

signal.signal(signal.SIGTERM, handle_signal)

在这种情况下,你可能会考虑在信号处理程序中调用del your_object,但即使如此,如果程序中仍然存在对该对象的引用(请参阅__del__文档),也不能保证调用__del__方法。
因此,我的建议是不要指望在依赖于SIGTERM关闭Python程序时一切都能绝对顺利和可预测。

1
sys.exit会引发SystemExit异常,因此它会自动运行__exit__清理代码。 - Kevin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接