Destruktor in Metaklasse Singleton-Objekt

8

Ich ändere eine Legacy-Bibliothek, die das Singleton-Muster durch den Metaklassen-Ansatz verwendet.

Die Singleton-Klasse, die von type erbt, definiert de __call__ function.

Im Moment wird mein Singleton-Objekt, das diese Bibliothek verwendet, niemals gelöscht. Ich habe die Methode __del__ in den Singleton-Klassen definiert und diese Funktion wird nie aufgerufen.

Klarstellung: Ich habe eine (Meta-) Klasse namens Singleton implementiert, die von mehreren Klassen verwendet wird, wobei Singleton als __metaclass__ verwendet wird.

Ich habe zum Beispiel class A(object) , das __metaclass__ = Singleton hat. Die A-Klasse hat mehrere Mitglieder, die ich zerstören möchte, wenn mein Programm endet und das A-Objekt (das einzige, das existieren kann) zerstört ist.

Ich habe versucht, __del__ method in A class zu definieren, aber es funktioniert nicht.

    
JoseLSegura 10.03.2016, 11:47
quelle

1 Antwort

6

Punkt 1: __del__() darf nicht am Prozess exit

aufgerufen werden

Das erste, was ich sagen soll, ist

  

Es ist nicht garantiert, dass __del__() -Methoden für Objekte aufgerufen werden, die noch existieren, wenn der Interpreter beendet wird.

Von den Python-Datenmodelldokumenten . Daher solltest du dich nicht darauf verlassen, dass du den Zustand aufräumst, den du beim Beenden aufräumen musst, und auf der höchsten Ebene, weshalb dein __del__() möglicherweise nicht aufgerufen wird. Dafür steht atexit .

Punkt 2: Vorhersagbare Objektlebensdauern ist ein Implementierungsdetail in Python

Als Nächstes möchte ich sagen, dass CPython die Referenzzählung verwendet, um zu erkennen, dass ein Objekt freigegeben werden kann, ohne den Garbage Collector verwenden zu müssen (was zu besser vorhersagbaren CPU-Auswirkungen und potenziell effizienteren Anwendungen führt) eine Zirkelreferenz, eine ungereinigte Ausnahme, eine vergessene Schließung oder eine andere Python-Implementierung zum Brechen, und Sie sollten sich wirklich wirklich fragen, ob Sie sich darauf verlassen wollen, dass __del__() an einem bestimmten Punkt aufgerufen wird .

Punkt 3: Singleton-Implementierungen pflegen im Allgemeinen eine globale Referenz auf die Singleton-Instanz

Nach dem Klang würde ich vermuten, dass Ihre Singleton-Metaklasse (selbst ein Singleton ...) Ihre Singleton-Instanz beim ersten Aufruf von __call__() beibehält. Da die Metaklasse nicht freigegeben wird, da sie zu dem Modul gehört, das selbst von sys.modules beibehalten wird, wird diese Referenz nicht bis zum Ende des Programms verschwinden, so dass auch bei einer garantierten sofortigen Aufräumung aller externen Referenzen darauf verzichtet wird Wenn der Singleton freigegeben wird, wird Ihr __del__() nicht aufgerufen.

Was Sie ausprobieren könnten

  1. Fügen Sie einen atexit -Handler hinzu, wenn Sie Ihre Singleton-Instanz erstellen, um beim Prozess-Exit die notwendigen Aufräumarbeiten auszuführen.
  2. Mach das auch in der __del__() -Methode auf, wenn du willst. ZB können Sie sich für die Ordentlichkeit / zukünftige Erweiterbarkeit (z. B. Pluralisieren des Singletons) entscheiden, dass die Singleton-Instanz nach sich selbst aufgeräumt werden soll, wenn sie nicht mehr verwendet wird.
    • Und wenn Sie eine __del__() -Methode implementieren, die erwartet, dass während der normalen Programmausführung aufgeräumt werden soll, werden Sie wahrscheinlich auch den atexit -Handler entfernen wollen.
  3. Wenn Sie möchten, dass Ihr Singleton bereinigt wird, wenn niemand es mehr verwendet, sollten Sie es in Ihrer Metaklasse speichern, indem Sie weakref , damit Sie es nicht selbst behalten.
daphtdazz 12.12.2016 14:08
quelle