__del__在退出时的行为

4
我有一个test.py文件:
class A:
    def __init__(self):
        print("A init")

    def __del__(self):
        print("A del")

a = A()

当我运行它10次(python3 test.py),它总是产生下一个输出:

A init
A del

但是,如果我在脚本结尾添加 sys.exit 呼叫:

import sys

class A:
    def __init__(self):
        print("A init")

    def __del__(self):
        print("A del")

a = A()

sys.exit(-1)

在10次测试中,有5次(随机的)我会遇到以下问题:
A init

并且在一半的情况下:

A init
A del    

我在 Windows 7 x64 上使用 Python3.4.3 [MSC v.1600 32 bit]。那么为什么 __del__ 方法不是每次都被调用?我需要使用其他退出方法来传递脚本的返回代码并确保所有析构函数都被执行吗?还有一个相关的问题:是否可能在收到来自操作系统的 SIGTERM 或 SIGKILL 时执行析构函数?

8
如果您想确保清理方法被调用,请考虑使用上下文管理器。 - jonrsharpe
5
几乎从不使用__del__。您可以使用signal模块捕获信号,除了无法被捕获的SIGKILL信号。 - L3viathan
另外,使用 sys.exit(0); 表示代码正常运行结束。 - AMACB
1
我想使用__del__的原因是,我正在编写一个包装器来处理一些.so库,该库与某些操作系统音频资源一起工作,并且明确指出我必须在退出时调用某些deinit方法,否则在下次启动时与库一起工作时可能会出现问题,这只能在重新启动后才能解决。因此,我想在__del__中调用包装器类。也许更好的决定是将deinit分离到其他方法中,并完全依赖于包装器的用户? - Ivan Borshchov
我想将-1作为返回代码传递,仅作为示例。 - Ivan Borshchov
1
除了 SIGKILL 和 SIGSTOP 之外,@L3viathan - Emmanuel Meric de Bellefon
1个回答

4

根据文档

不能保证在解释器退出时仍然存在的对象会调用__del__()方法。

如果您想确保调用a.__del__,则必须显式删除实例:

a = A()
del a   # Assuming this is the final reference to the object

3
值得注意的是,调用 del a 并不一定意味着对象的 __del__ 方法会被调用。只有在使用CPython且没有其他对该对象的引用时才能确定。在其他情况下,这可能取决于垃圾回收器的心情。 - Blckknght

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