无法在__del__()中引用导入的模块
我在使用一个对象的 __del__()
方法来取消它对某个事件的订阅(这个事件系统的工作方式类似于这个):
import my_enviroment
class MyClass():
def __del__(self):
my_environment.events.my_event -= self.event_handler_func
奇怪的是,在程序运行结束时,我收到了以下错误:
Exception AttributeError: "'NoneType' object has no attribute 'events'" in <bound method MyClass.__del__ of <myclass.MyClass instance at 0x04C54580>> ignored
这怎么可能呢?! my_environment
是我导入的一个模块,怎么会变成 None 呢?(events
是它里面的一个全局对象,包含像 my_event
这样的事件钩子)
2 个回答
4
如果你查看Python的文档,就会发现当程序结束时,所有对象都会被销毁,这个过程就像机器拆解一样。这意味着你依赖的一些东西,比如全局变量,可能在这个时候已经不复存在了。
所以,你需要做的是确保那些需要调用__del__
的方法的对象在程序结束之前就被销毁。更好的办法是把这些对象做成上下文管理器,也就是有__enter__
和__exit__
方法的对象,然后在with
语句中使用它们。或者,你也可以把__del__
里的代码放在try-except
块中,这样即使出现异常也不会影响程序结束,前提是这些代码在程序结束时不是特别重要。
7
根据Python文档关于__del__
的说明:
[...]
__del__()
方法中引用的其他全局变量可能已经被删除,或者正在被清理(比如导入机制正在关闭)。因此,__del__()
方法应该尽量只做维持外部状态所需的最小操作。
换句话说,当你的对象调用__del__
方法时,my_enviroment
可能已经被Python“删除”了,所以它可能会变成None……