TL/DR:scaricare un modulo 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 Ho contattato gli sviluppatori Python su questo problema e in effetti si tratta di not going to be possible to unload a module completamente "in prossimi cinque anni". (vedi il link)
Si prega di accettare che Python infatti non supporta i moduli di scarico per gravi, fondamentali, insormontabili, problemi tecnici, in 2.x.
Durante il mio recente caccia di un memleak nella mia app, ho ristretto la scelta a moduli, vale a dire la mia incapacità di spazzatura raccogliere un modulo scaricato. Utilizzando , qualsiasi metodo elencato di seguito per scaricare un modulo lascia migliaia di oggetti in memoria. In altre parole: non riesco a scaricare un modulo in Python ...
Il resto della domanda è cercare di raccogliere un modulo in qualche modo. prova
Let:
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
Salviamo una copia di sys.modules
per tentare di ripristinare in un secondo momento. Quindi, questo è un oggetto di riferimento 4074. Dovremmo idealmente tornare a questo in qualche modo.
Diamo importare un modulo:
import httplib
print len(gc.get_objects()) # 7063 objects in memory
Siamo fino a 7K oggetti non spazzatura. Proviamo a rimuovere httplib
da sys.modules
.
sys.modules.pop('httplib')
gc.collect()
print len(gc.get_objects()) # 7063 objects in memory
Bene, questo non ha funzionato. Hmm, ma non c'è un riferimento in __main__
? Oh, sì:
del httplib
gc.collect()
print len(gc.get_objects()) # 6746 objects in memory
Urrà, giù 300 oggetti. Tuttavia, nessun sigaro, è più di 4000 oggetti originali. Proviamo a ripristinare sys.modules
dalla copia.
sys.modules = sm
gc.collect()
print len(gc.get_objects()) # 6746 objects in memory
Hmmm, bene che era inutile, nessun cambiamento .. Forse se cancelliamo globali ...
globals().clear()
import gC# we need this since gc was in globals() too
gc.collect()
print len(gc.get_objects()) # 6746 objects in memory
gente del posto?
locals().clear()
import gC# we need this since gc was in globals() too
gc.collect()
print len(gc.get_objects()) # 6746 objects in memory
Cosa .. cosa succederebbe se imported
un modulo all'interno di 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
Ora, questo non è giusto, ha importato in __main__
, perché? Non avrebbe dovuto lasciare mai il local_dict
... Argh! Torniamo a importare completamente httplib
. Forse se lo abbiamo sostituito con un oggetto fittizio?
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
moduli Die, die !!
import httplib
for attr in dir(httplib):
setattr(httplib, attr, None)
gc.collect()
print len(gc.get_objects()) # 6749 objects in memory
va bene, dopo tutti i tentativi, il migliore è 2675 (quasi + 50%) dal punto di partenza ... Questo è solo da un modulo ... Che non ha nemmeno nulla di grande dentro ...
Ok, ora sul serio, dov'è il mio errore? Come posso scaricare un modulo e cancellare tutto il suo contenuto? Oppure i moduli di Python sono una perdita di memoria gigante?
sorgente completo nel più semplice per copiare forma: http://gist.github.com/450606
Sì, carica un numero ragionevolmente illimitato di moduli: è un server di applicazioni Web che accetta nuove revisioni del proprio codice sorgente e lo ricarica (è un'attività web piuttosto standard). La perdita è dovuta al fatto che il vecchio codice è ancora disponibile in memoria, anche se sostituito, anche se non raggiungibile ... –
Python supporta i moduli di scarico. Sono spazzatura raccolti, come ogni altro oggetto in Python. –
@Slava: potresti dare un'occhiata al codice sorgente a 'mod_python', che ha il suo importatore che è progettato per gestire i moduli di ricarica senza produrre perdite di memoria. Potrebbe esserci del codice che potresti usare. –