2009-02-22 15 views
14

Zawsze zakłada się, że plik będzie przeciekać, jeżeli został otwarty bez zamknięta, ale po prostu sprawdzeniu, że jeśli wprowadzić następujące linie kodu, plik zostanie zamknięty:Jak Python zamyka pliki, które zostały gc'ed?

>>> f = open('somefile.txt') 
>>> del f 

Tak z czystej ciekawości , jak to działa? Zauważyłem, że ten plik nie zawiera metody __ del __.

Odpowiedz

19

W języku co najmniej CPython pliki są zamykane, gdy obiekt pliku jest dezalokowany. Zobacz funkcję file_dealloc w Objects/fileobject.c w źródle CPython. Metody dealloc są podobne do __del__ dla typów C, z wyjątkiem braku niektórych problemów związanych z __del__.

+1

Aby wyjaśnić, __del__ jest wywoływany podczas czyszczenia pamięci, a także w implementacji C w Pythonie dla obiektów plików, które występują w momencie, gdy nie ma już odwołań do obiektu pliku. –

4

Stąd oświadczenie z.

dla Pythona 2.5, użyj

from __future__ import with_statement 

(dla Pythona 2.6 lub 3.x, nic nie robić)

with open("someFile", "rU") as aFile: 
    # process the file 
    pass 
# At this point, the file was closed by the with statement. 
# Bonus, it's also out of scope of the with statement, 
# and eligible for GC. 
+0

Tak też się założyłem. Ale w systemie OS X w Pythonie 2.5.1 wiersze kodu, które zamieściłem, powodują, że interpreter języka Python zwolni plik (zweryfikowany w Monitorze aktywności). –

+0

Python powinien zamknąć plik po jego zebraniu. Szukałem, gdzie to się dzieje w fileobject.c, ale go tam nie ma. Prawdopodobnie jest to gdzieś w mechanizmie gc, gdzie właśnie szukam. Podoba mi się to pytanie. –

+0

Wygląda na to, że przegapiłem go w fileobject.c (zobacz Gallagher). Naprawdę chciałbym mieć lepsze zrozumienie wewnętrznych elementów CPython. –

0

Najlepszy Domyślam się, że ponieważ typ pliku jest wbudowany typ, sam interpreter obsługuje zamykanie pliku podczas zbierania śmieci.

Alternatywnie, sprawdzasz tylko po wyjściu interpretera python, a wszystkie "wyciekłe" uchwyty plików są i tak zamknięte.

+0

Moje rozumienie "typu pierwotnego" (otrzymanego z Java) nie pozostawia pliku jako prymitywnego, ponieważ w Pythonie nie ma żadnych prymitywów. –

+1

Myślę, że HUAGHAGUAH chciał powiedzieć "wbudowany typ". :) –

2

Python używa licznika odwołań i destrukcji deterministycznej oprócz zbierania śmieci. Gdy nie ma więcej odniesień do obiektu, obiekt jest natychmiast zwalniany. Zwolnienie pliku zamyka go.

To jest inne niż np. Java, w której istnieje tylko niedeterministyczne zbieranie śmieci. Oznacza to, że konotujesz wiedzieć, kiedy obiekt zostanie zwolniony, więc będziesz musiał zamknąć plik ręcznie.

Należy pamiętać, że liczenie odwołań nie jest idealne. Możesz mieć obiekty z odwołaniami cyklicznymi, których nie można uzyskać z progamu. Właśnie dlatego w Pythonie oprócz liczenia odwołań jest zbierane śmieci.