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
Pertinente: https://stackoverflow.com/ q/15974561/1959808 –