元类Singleton对象中的析构函数

时间:2016-03-10 11:47:17

标签: python singleton destructor metaclass

我正在通过元类方法修改使用单例模式的遗留库。

继承自type的Singleton类定义了de __call__函数。

现在,我永远不会删除使用此库的单例对象。我在单例类中定义了__del__方法,并且从不调用该函数。

澄清:我已经实现了一个名为Singleton的(meta)类,它由几个类使用,使用Singleton作为__metaclass__

例如,我有class A(object),有__metaclass__ = Singleton。当我的程序结束时,A类有几个我想要被销毁的成员,并且A对象(唯一可以存在的对象)被销毁。

我尝试在__del__类中定义A方法,但它不起作用。

1 个答案:

答案 0 :(得分:6)

第1点:在进程退出时可能不会调用__del__()

首先要说的是

  

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

来自the python data model docs。因此,你不应该依赖它来整理你需要在退出时整理的状态,并且在最高级别,这就是为什么你的__del__()可能没有被调用的原因。这是atexit的用途。

第2点:可预测的对象生存期是python

中的实现细节

接下来要说的是,虽然CPython使用引用计数来使其能够检测到可以在不使用垃圾收集器的情况下释放对象(导致更可预测的CPU影响和可能更高效的应用程序),但它只需要一个循环引用,一个未清除的异常,一个被遗忘的闭包或一个不同的python实现来打破,所以你应该认真地真的很难想你是否要依赖于__del__()被调用特别要点。

第3点:Singleton实现通常维护对单例实例的全局引用

通过它的声音,我猜你的单身元类(本身就是单身......)在第一次调用__call__()时保留你的单例实例。由于元类没有被释放,因为它属于模块,它本身由sys.modules保留,该引用在程序终止时不会消失,所以即使给出了保证提示整理所有外部对被释放的单身人士的引用,你的__del__()不会被调用。

你可以尝试什么

  1. 在创建单例实例时添加atexit处理程序,以便在进程退出时进行必要的整理。
  2. 如果您愿意,也可以使用__del__()方法进行整理。例如,您可以决定整体/未来的可扩展性(例如,复数单例),您希望单例实例在不再使用时自行整理。
    • 如果你实现一个__del__()方法,希望在正常的程序执行期间完成整理,你可能也想要删除atexit处理程序。
  3. 如果您希望在没有人使用它时清理您的单身人士,请考虑使用weakref将其存放在您的元类上,这样您就不会自己保留它。