TL/DR:Unload ein Modul in Python
import gc, sys
print len(gc.get_objects()) # 4073 objects in memory
# Attempt to unload the module
import httplib
del sys.modules["httplib"]
httplib = None
gc.collect()
print len(gc.get_objects()) # 6745 objects in memory
UPDATE Ich habe Python-Entwickler über dieses Problem in Kontakt gebracht und in der Tat ist es not going to be possible to unload a module vollständig "in nächsten fünf Jahren". (siehe Link)
Bitte akzeptieren Sie, dass Python in der Tat keine Entlade-Module für schwere, grundlegende, unüberwindbare, technische Probleme in 2.x unterstützt.
Während meiner letzten Jagd nach einem memleak in meiner app, ich habe es verengt Module nach unten, nämlich meine Unfähigkeit, Müll sammeln ein unbelasteter Modul. Wenn Sie eine beliebige Methode verwenden, um ein Modul zu entladen, bleiben Tausende von Objekten im Speicher. Mit anderen Worten - ich kann ein Modul in Python nicht entladen ...
Der Rest der Frage ist der Versuch Müll irgendwie ein Modul zu sammeln.
Lassen Sie uns versuchen:
import gc
import sys
sm = sys.modules.copy() # httplib, which we'll try to unload isn't yet
# in sys.modules, so, this isn't the source of problem
print len(gc.get_objects()) # 4074 objects in memory
Lassen Sie uns eine Kopie sys.modules
speichern, zu versuchen, es später wieder herzustellen. Also, das ist eine Baseline 4074 Objekte. Wir sollten im Idealfall darauf zurückkommen.
Lasst uns ein Modul importieren:
import httplib
print len(gc.get_objects()) # 7063 objects in memory
Wir sind bis zu 7K Nicht-Müll-Objekte. Versuchen wir, httplib
von sys.modules
zu entfernen.
sys.modules.pop('httplib')
gc.collect()
print len(gc.get_objects()) # 7063 objects in memory
Nun, das hat nicht funktioniert. Hmm, aber gibt es keine Referenz in __main__
? Oh, yeah:
del httplib
gc.collect()
print len(gc.get_objects()) # 6746 objects in memory
Hurra, runter 300 Objekte. Immer noch keine Zigarre, das sind weit mehr als 4000 Originalobjekte. Versuchen wir, sys.modules
von Kopie wiederherzustellen.
sys.modules = sm
gc.collect()
print len(gc.get_objects()) # 6746 objects in memory
Hmmm, na ja, das war sinnlos, keine Änderung .. Vielleicht, wenn wir Globals auszulöschen ...
globals().clear()
import gC# we need this since gc was in globals() too
gc.collect()
print len(gc.get_objects()) # 6746 objects in memory
Einheimischen?
locals().clear()
import gC# we need this since gc was in globals() too
gc.collect()
print len(gc.get_objects()) # 6746 objects in memory
Was .. was ist, wenn wir imported
ein Modul innerhalb von exec
?
local_dict = {}
exec 'import httplib' in local_dict
del local_dict
gc.collect()
print len(gc.get_objects()) # back to 7063 objects in memory
Nun, das ist nicht fair, es importiert sie in __main__
, warum? Es sollte nie die local_dict
verlassen haben ... Argh! Wir zurück zu vollständig importiert httplib
. Vielleicht, wenn wir es durch ein Dummy-Objekt ersetzt haben?
from types import ModuleType
import sys
print len(gc.get_objects()) # 7064 objects in memory
Bloody ..... !!
sys.modules['httplib'] = ModuleType('httplib')
print len(gc.get_objects()) # 7066 objects in memory
Die Module, sterben !!
import httplib
for attr in dir(httplib):
setattr(httplib, attr, None)
gc.collect()
print len(gc.get_objects()) # 6749 objects in memory
Okay, nachdem alle Versuche, das Beste ist, 2675 (fast + 50%) ab Punkt ... Das ist nur ein Modul aus ... Das ist nicht einmal etwas groß im Innern hat ...
Ok, jetzt ernsthaft, wo ist mein Fehler? Wie kann ich ein Modul entladen und alle Inhalte löschen? Oder haben Pythons Module ein riesiges Speicherleck?
Voll Quelle in einfacher Form zu kopieren: http://gist.github.com/450606
Ja, es lädt einigermaßen unbegrenzte Anzahl von Modulen - es ist ein Web-App-Server, der neue Revisionen seines eigenen Quellcodes akzeptiert und neu lädt (das ist ziemlich Standard-Web-Aufgabe). Das Leck ist von der Tatsache, dass alte Code immer noch da draußen im Speicher ist, auch wenn ersetzt, auch wenn nicht erreichbar ... –
Python unterstützt das Entladen von Modulen. Sie sind Müll gesammelt, wie jedes andere Objekt in Python. –
@Slava: Sie können sich den Quellcode von 'mod_python' ansehen, der über einen eigenen Importer verfügt, der das erneute Laden von Modulen ermöglicht, ohne Speicherlecks zu erzeugen. Möglicherweise gibt es dort einen Code, den Sie verwenden könnten. –