python - 元类单例对象中的析构函数

标签 python singleton destructor metaclass

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

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

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

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

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

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

最佳答案

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

首先要说的是

It is not guaranteed that __del__() methods are called for objects that still exist when the interpreter exits.

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

要点2:可预测的对象生命周期是python中的一个实现细节

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

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

根据它的声音,我猜你的单例元类(本身就是一个单例......)在第一次调用 __call__() 时保留了你的单例实例。由于元类属于模块,因此未发布,而模块本身由 sys.modules 保留,因此该引用不会在程序终止时消失,因此即使给出有保证的提示清理对正在释放的单例的所有外部引用,您的 __del__() 将不会被调用。

你可以尝试什么

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

关于python - 元类单例对象中的析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35915624/

相关文章:

python - 无法将小部件放置在框架 tkinter 上

c++ - 如何在共享库的整个生命周期中存储数据

c++ - 销毁期间派生的成员(member)国

c++ - 析构函数是在 main() 的末尾调用的;奇怪的行为

c++ - 为什么在创建数组期间在 C++ 中抛出未捕获的异常时不调用析构函数?

python - 字典的键的交集是什么

python - Tensorflow:如何在约束下最小化

python - Django Celery Scrappy 错误 : twisted. internet.error.ReactorNotRestartable

Laravel `between app->bind` 和 `app->singleton` 的区别?

javascript - 具有缓存静态属性的 JavaScript 单例模式如何工作?