2011-11-06 11 views

risposta

23

Il meccanismo di conteggio di riferimento standard di Python non può liberare i cicli, quindi la struttura nell'esempio potrebbe perdere.

Il supplemental garbage collection facility, però, è abilitato per impostazione predefinita e dovrebbe essere in grado di liberare quella struttura, se nessuno dei suoi componenti è raggiungibile dall'esterno più e non hanno __del__() metodi.

Se lo fanno, il netturbino will not free them perché non può determinare un ordine sicuro per eseguire questi metodi __del__().

+5

Va detto esplicitamente che il GC che chiami "supplementare" è abilitato di default in Python –

+0

@Eli, hai ragione, la risposta è aggiornata di conseguenza. –

+3

Evviva! Almeno, i popoli (tu e Raymond Hettinger) che non fanno confusione su GC e refs counter e che non usano "garbage collector" come sinonimo di "meccanismo di conteggio dei riferimenti"! Sono rimasto perplesso per molto tempo sul fatto di aver capito cose del genere ma stavo leggendo costantemente testi in cui le persone esprimevano le loro idee come se il GC fosse il responsabile dell'uccisione di oggetti non più referenziati. Nella tua risposta, la differenza è perfettamente espressa e chiara. Grazie. Quindi +1 – eyquem

5

GC Python è progettato per attraversare tutti gli oggetti attivi per individuare ed eliminare cicli di riferimento senza riferimenti esterni.

È possibile verificare ciò che sta accadendo eseguendo e quindi stampando gc.garbage e gc.get_objects.

2

Se si utilizza weakrefs per i puntatori padre, GC avverrà normalmente.

18

Per estendere un po 'la risposta di Frédéric, the "reference counts" section dei documenti spiega bene il rilevamento del ciclo supplementare.

poiché trovo spiegare le cose un buon modo per confermare lo capisco, ecco alcuni esempi ... Con queste due classi:

class WithDel(object): 
    def __del__(self): 
     print "deleting %s object at %s" % (self.__class__.__name__, id(self)) 


class NoDel(object): 
    pass 

Creazione di un oggetto e di perdere il riferimento dalla a innesca il metodo __del__ , grazie al ref conteggio:

>>> a = WithDel() 
>>> a = None # leaving the WithDel object with no references 
deleting WithDel object at 4299615184 

Se facciamo un ciclo di riferimento tra due oggetti con nessun metodo__del__, tutto è ancora esente da perdite, t il suo tempo grazie al rilevamento del ciclo.In primo luogo, abilitare l'uscita garbage collection debug:

>>> import gc 
>>> gc.set_debug(gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_OBJECTS) 

Poi fare un ciclo di riferimento tra i due oggetti:

>>> a = NoDel(); b = NoDel() 
>>> a.other = b; b.other = a # cyclical reference 
>>> a = None; b = None # Leave only the reference-cycle 
>>> gc.collect() 
gc: collectable <NoDel 0x10046ed50> 
gc: collectable <NoDel 0x10046ed90> 
gc: collectable <dict 0x100376c20> 
gc: collectable <dict 0x100376b00> 
4 
>>> gc.garbage 
[] 

(il dict da oggetti attributo internal __dict__)

Tutto va bene, fino al anche uno degli oggetti nel ciclo contiene un metodo __del__:

>>> a = NoDel(); b = WithDel() 
>>> a.other = b; b.other = a 
>>> a = None; b = None 
>>> gc.collect() 
gc: uncollectable <WithDel 0x10046edd0> 
gc: uncollectable <dict 0x100376b00> 
gc: uncollectable <NoDel 0x10046ed90> 
gc: uncollectable <dict 0x100376c20> 
4 
>>> gc.garbage 
[<__main__.WithDel object at 0x10046edd0>] 

Come accennato Paul, il ciclo può essere interrotto con un weakref:

>>> import weakref 
>>> a = NoDel(); b = WithDel() 
>>> a.other = weakref.ref(b) 
>>> b.other = a # could also be a weakref 

Poi, quando si perde il b riferimento all'oggetto WithDel, esso viene eliminato, nonostante il ciclo:

>>> b = None 
deleting WithDel object at 4299656848 
>>> a.other 
<weakref at 0x10045b9f0; dead> 

Oh, objgraph sarebbe utile indicated the problematic __del__ method like this

+0

Questo funziona per me in python2, tuttavia, in python3 non riesco a riprodurre la fuga ... Qualcosa è cambiato? – kralyk

+0

@kralyk Immagino che questo pep sia responsabile: https://www.python.org/dev/peps/pep-0442/ – ead

Problemi correlati