2010-04-05 19 views
6

Próbuję zrozumieć wewnętrzne elementy odśmiecacza CPython, szczególnie gdy wywoływany jest destruktor. Do tej pory zachowanie jest intuicyjne, ale następujący przypadek wywołuje mnie:Dlaczego wywoływany jest destruktor, gdy moduł usuwania śmieci CPython jest wyłączony?

  1. Wyłącz GC.
  2. Utwórz obiekt, a następnie usuń odniesienie do niego.
  3. Obiekt zostanie zniszczony i zostanie wywołana metoda _____del_____.

Pomyślałem, że tak się stanie tylko wtedy, gdy włączony jest garbage collector. Czy ktoś może wyjaśnić, dlaczego tak się dzieje? Czy istnieje sposób na odroczenie wywoływania destruktora?

import gc 
import unittest 

_destroyed = False 

class MyClass(object): 

    def __del__(self): 
     global _destroyed 
     _destroyed = True 

class GarbageCollectionTest(unittest.TestCase): 

    def testExplicitGarbageCollection(self): 
     gc.disable() 
     ref = MyClass() 
     ref = None 
     # The next test fails. 
     # The object is automatically destroyed even with the collector turned off. 
     self.assertFalse(_destroyed) 
     gc.collect() 
     self.assertTrue(_destroyed) 

if __name__=='__main__': 
    unittest.main() 

Uwaga: Ten kod nie jest przeznaczona do produkcji - Ja już zauważyć, że jest to bardzo specyficzne i implementacja nie działa na Jython.

Odpowiedz

9

Python ma zarówno odniesienia licząc zbierania śmieci i cykliczny zbierania śmieci, i to, że ten ostatni Moduł kontroluje gc. Zliczanie referencji nie może być wyłączone, a zatem nadal dzieje się, gdy cykliczny garbage collector jest wyłączony.

Ponieważ nie ma żadnych odniesień do obiektu po ref = None, jego metoda __del__ jest wywoływana w wyniku zerowania liczby odwołań.

Istnieje pewna wskazówka w : "Ponieważ kolektor uzupełnia licznik odwołań już używany w Pythonie ..." (mój nacisk).

można zatrzymać pierwsze twierdzenie wypalania poprzez przedmiot odnoszą się do siebie, tak, że jego licznik odwołań nie wychodzi na zero, na przykład poprzez nadanie mu tego konstruktora:

def __init__(self): 
    self.myself = self 

ale jeśli zrób to, drugie twierdzenie zostanie odpalone. Dzieje się tak dlatego, że cykle śmieci z metodami __del__ nie są gromadzone - patrz dokumentacja dla gc.garbage.

4

W zależności od twojej definicji śmieciarza, CPython ma dwa garbage collectory, odniesienie odliczające i drugie.
Licznik odniesienia działa zawsze i nie może być wyłączony, ponieważ jest dość szybki i lekki, co nie wpływa znacząco na czas działania systemu.
Drugi (jakikolwiek inny znacznik i zamiatanie, jak sądzę), uruchamia się tak często i może być wyłączony. Dzieje się tak, ponieważ wymaga on, aby interpreter był wstrzymany podczas działania, co może nastąpić w niewłaściwym momencie i pochłania sporo czasu procesora.
Ta możliwość wyłączenia jest dostępna w tym czasie, kiedy spodziewasz się zrobić coś krytycznego, a brak tego GC nie spowoduje żadnych problemów.

+0

Czy to udokumentowano implementację "dwóch śmieciarzy"? – Frederik

+0

Spójrz na odpowiedź Alexa Martellego i związane z nim linki. To chyba lepsze niż wszystko, co mogłem wymyślić. –

4

Docs here wyjaśnić w jaki sposób to, co nazywa się „opcja śmieciarza” jest w rzeczywistości kolekcjonerem cyklicznego śmieci (rodzaju, że liczenie odniesienia nie złapać).Zliczanie odniesienia jest wyjaśnione here, z ukłonem jego współdziałaniu z GC cyklicznego:

Podczas Python używa tradycyjnej realizację odniesienia liczenia, to oferuje również detektor cyklu że działa do wykrywania cykli odniesienia. Ten numer pozwala aplikacjom nie martwić się o bezpośrednie lub pośrednie odwołania do odwołań kołowych; są to słabe strony zbierania śmieci zaimplementowane przy użyciu tylko liczenia odwołań . Referencje cykli składają się z obiektów, które zawierają (ewentualnie pośrednie) odniesienia dla siebie, tak aby każdy obiekt w cykl miał liczbę odniesienia, która jest niezerowa. Typowe implementacje odniesienia liczenia nie są w stanie odzyskać pamięć należącej do żadnej obiektów w cyklu odniesienia lub odwołanie od obiektów w cyklu , choć nie ma dalsze odniesienia do cyklu samego.

Powiązane problemy