W Pythonie, jeśli otworzysz plik bez wywołania close()
lub zamkniesz plik, ale nie używasz try
- finally
lub instrukcji " with
", czy to jest problem? A może jako praktyka kodowania wystarczy polegać na wyrzucaniu elementów bezużytecznych w Pythonie, aby zamknąć wszystkie pliki? Na przykład, jeśli to zrobi:
for line in open("filename"):
# ... do stuff ...
... czy jest to problem, ponieważ pliku nigdy nie można zamknąć i może wystąpić wyjątek uniemożliwiający jego zamknięcie? A może na pewno zostanie zamknięty po zakończeniu for
oświadczenia, ponieważ plik wykracza poza zakres?
python
file
garbage-collection
user553702
źródło
źródło
for
bloku. Jego liczba odwołań spadnie do zera, powodując automatyczne zamknięcie, ale tylko funkcje, klasy i moduły definiują zakresy w Pythonie, a nie inne instrukcje złożone.for
blokami a funkcjami / klasami / modułami. To znacznie prostsze: obiekty nie mają zasięgów, tylko nazwy mają. Nie ma nazwy odnoszącej się do tego obiektu, więc nie ma tu nic, co mogłoby pozostać w zakresie lub wyjść poza zakres.for
pętla jest związana z zakresem i wspomina, że plik zostaje zamknięty z zupełnie innego powodu. Nie chodzi o to, jakie zakresy są w Pythonie, ponieważ nie ma to znaczenia.Odpowiedzi:
W twoim przykładzie nie ma gwarancji, że plik zostanie zamknięty przed zamknięciem interpretera. W obecnych wersjach CPythona plik zostanie zamknięty na końcu pętli for, ponieważ CPython używa zliczania odwołań jako podstawowego mechanizmu usuwania pamięci, ale jest to szczegół implementacji, a nie funkcja języka. Nie ma gwarancji, że inne implementacje Pythona będą działać w ten sposób. Na przykład IronPython, PyPy i Jython nie używają liczenia odwołań i dlatego nie zamykają pliku na końcu pętli.
Poleganie na implementacji czyszczenia pamięci w CPythonie jest złą praktyką, ponieważ sprawia, że kod jest mniej przenośny. Możesz nie mieć wycieków zasobów, jeśli używasz CPython, ale jeśli kiedykolwiek przełączysz się na implementację Pythona, która nie korzysta z liczenia odwołań, musisz przejść przez cały kod i upewnić się, że wszystkie pliki są poprawnie zamknięte.
Na przykład użyj:
źródło
with open() as f
automatycznie zamyka plik po zakończeniu?with
zapewnia instrukcja, ale oczywiście, aby ta magia działała, obiekt musi mieć specjalne metody,__enter__
a__exit__
w tym drugim przypadku obiekt musi wykonaćclose
wszystkie inne czynności porządkowe, które należy wykonać w koniecwith
wypowiedzi ...Niektóre Pythony zamkną pliki automatycznie, gdy nie są już przywoływane, podczas gdy inne nie będą, a system operacyjny musi zamknąć pliki po zakończeniu pracy interpretera Pythona.
Nawet dla Pythonów, które zamkną pliki za Ciebie, czas nie jest gwarantowany: może nastąpić natychmiast lub może to być sekundy / minuty / godziny / dni później.
Tak więc, chociaż możesz nie mieć problemów z używanym językiem Python, zdecydowanie nie jest dobrą praktyką pozostawianie otwartych plików. W rzeczywistości w cpythonie 3 otrzymasz teraz ostrzeżenia, że system musiał zamknąć pliki, jeśli tego nie zrobiłeś.
Morał: posprzątaj po sobie. :)
źródło
Chociaż użycie takiej konstrukcji w tym konkretnym przypadku jest całkiem bezpieczne, istnieją pewne zastrzeżenia dotyczące uogólnienia takiej praktyki:
źródło
Plik pobiera śmieci, a tym samym jest zamykany. GC określa, kiedy zostanie zamknięty, a nie Ty. Oczywiście nie jest to zalecana praktyka, ponieważ możesz przekroczyć limit otwierania plików, jeśli nie zamykasz plików zaraz po zakończeniu ich używania. Co jeśli w tej swojej
for
pętli otworzysz więcej plików i zostawisz je na swoim miejscu?źródło
for
instrukcji - nie będziesz musiał czekać na następne uruchomienie czyszczenia pamięci.Cześć Bardzo ważne jest, aby zamknąć deskryptor pliku w sytuacji, gdy zamierzasz użyć jego zawartości w tym samym skrypcie Pythona. Dziś sam zdaję sobie sprawę, po tak długim hektarnym debugowaniu. Powodem jest to, że zawartość będzie edytowana / usuwana / zapisywana dopiero po zamknięciu deskryptora pliku i wpłynie to na zmiany w pliku!
Więc przypuśćmy, że masz sytuację, w której zapisujesz zawartość do nowego pliku, a następnie bez zamykania fd używasz tego pliku (nie fd) w innym poleceniu powłoki, które czyta jego zawartość. W takiej sytuacji nie otrzymasz zawartości polecenia powłoki zgodnie z oczekiwaniami, a jeśli spróbujesz debugować, nie możesz łatwo znaleźć błędu. możesz również przeczytać więcej na moim blogu http://magnificentzps.blogspot.in/2014/04/importance-of-closing-file-descriptor.html
źródło
Podczas procesu I / O dane są buforowane: oznacza to, że są przechowywane w tymczasowej lokalizacji przed zapisaniem do pliku.
Python nie opróżnia bufora - to znaczy nie zapisuje danych do pliku - dopóki nie jest pewne, że skończysz pisać. Jednym ze sposobów jest zamknięcie pliku.
Jeśli piszesz do pliku bez zamykania, dane nie trafią do pliku docelowego.
źródło