La chiusura esplicita dei file è importante?


149

In Python, se apri un file senza chiamare close()o chiudi il file ma non lo usi try- finallyo l' withistruzione " ", è un problema? Oppure è una pratica di codifica basarsi sulla garbage collection di Python per chiudere tutti i file? Ad esempio, se uno fa questo:

for line in open("filename"):
    # ... do stuff ...

... è un problema perché il file non può mai essere chiuso e potrebbe verificarsi un'eccezione che ne impedisce la chiusura? O sarà sicuramente chiuso alla conclusione fordell'affermazione perché il file non rientra nell'ambito di applicazione?


13
Il file non non andare fuori del campo di applicazione alla fine del forblocco. Il conteggio dei riferimenti andrà a zero, causando la chiusura automatica, ma solo funzioni, classi e moduli definiscono gli ambiti in Python, non altre istruzioni composte.
AGF

18
Non è un problema a meno che non sia un problema. A livello di sistema operativo, tutti i file aperti dallo script verranno chiusi alla chiusura dello script, quindi non è necessario preoccuparsi di chiudere i file negli script degli strumenti usa e getta. Tuttavia, i processi hanno un limite al numero di file aperti che possono mantenere, quindi potrebbe essere necessario prestare maggiore attenzione agli script di lunga durata o complessi. In ogni caso, è una buona abitudine chiudere i file.
Russell Borogove,

3
@agf: hai ragione sul fatto che il file non esca dall'ambito, ma non è correlato alla distinzione tra forblocchi e funzioni / classi / moduli. È molto più semplice di così: gli oggetti non hanno ambiti, ma solo i nomi. Non esiste un nome che si riferisca a questo oggetto, quindi qui non c'è nulla che rimanga nell'ambito o esca dall'ambito.
massimo

@max Il mio commento sta correggendo la sua ipotesi che ci sia un ambito associato al forciclo e menzionando che il file viene chiuso per un motivo completamente diverso. Non entra in quali ambiti si trovano in Python, in quanto non è rilevante qui.
AGF

@max c'è un riferimento implicito a quello per loop ... questo è un argomento di semantica
Peter R

Risposte:


126

Nel tuo esempio il file non è garantito per essere chiuso prima che l'interprete esca. Nelle attuali versioni di CPython il file verrà chiuso alla fine del ciclo for perché CPython utilizza il conteggio dei riferimenti come meccanismo principale di garbage collection ma è un dettaglio di implementazione, non una funzionalità del linguaggio. Altre implementazioni di Python non sono garantite per funzionare in questo modo. Ad esempio IronPython, PyPy e Jython non usano il conteggio dei riferimenti e quindi non chiuderanno il file alla fine del ciclo.

È una cattiva pratica fare affidamento sull'implementazione della garbage collection di CPython perché rende il codice meno portatile. Potresti non avere perdite di risorse se usi CPython, ma se mai passi a un'implementazione di Python che non usa il conteggio dei riferimenti dovrai esaminare tutto il tuo codice e assicurarti che tutti i tuoi file siano chiusi correttamente.

Per il tuo esempio usa:

with open("filename") as f:
     for line in f:
        # ... do stuff ...

8
L'utilizzo with open() as fchiude automaticamente il file al termine?
Rohan,

25
@Rohan sì, questa è la piccola magia fornita dall'affermazione with, ma ovviamente per far funzionare questa magia l'oggetto deve avere i metodi speciali __enter__e __exit__, in quest'ultimo caso, l'oggetto fa closequalsiasi altra cosa di pulizia che deve essere fatta al fine della withdichiarazione ...
Copperfield,

1
Cordiali saluti: Questa risposta spiega solo "quando sarebbe chiuso" ma non spiega "cosa succede se rimane aperto". Per quest'ultimo, leggi "Cosa succederebbe se un file rimanesse aperto?" parte in questa risposta ( askubuntu.com/questions/701491/… )
RayLuo

Inoltre, la mancata chiusura dei file può causare file troncati poiché il contenuto del file non è stato scaricato.
Erwan Legrand,

Quindi, se non chiudo il file, recupererò sicuramente la mia memoria una volta che il programma smetterà di funzionare? O devo davvero uscire da tutto l'interprete?
Pro Q

22

Alcuni Python chiuderanno i file automaticamente quando non sono più referenziati, mentre altri non lo faranno ed è compito dell'O / S chiudere i file quando esce l'interprete Python.

Anche per i Python che chiuderanno i file per te, il tempismo non è garantito: potrebbe essere immediatamente o potrebbe essere secondi / minuti / ore / giorni dopo.

Quindi, anche se potresti non riscontrare problemi con Python che stai utilizzando, non è sicuramente una buona pratica lasciare aperti i tuoi file. In effetti, in cpython 3 ora riceverai avvisi che il sistema ha dovuto chiudere i file per te se non l'hai fatto.

Morale: ripulisci dopo te stesso. :)


9
I file vengono chiusi quando non vengono più citati in CPython, ma questa non è una funzione della lingua. Se lo fosse, puoi tranquillamente fare affidamento su di esso.
Peter Graham,

9

Sebbene sia abbastanza sicuro usare tale costrutto in questo caso particolare, ci sono alcuni avvertimenti per generalizzare tale pratica:

  • run può potenzialmente esaurire i descrittori di file, sebbene improbabile, immagina di cercare un bug del genere
  • potresti non essere in grado di eliminare detto file su alcuni sistemi, ad esempio win32
  • se esegui qualcosa di diverso da CPython, non sai quando il file è chiuso per te
  • se si apre il file in modalità di scrittura o lettura-scrittura, non si sa quando i dati vengono scaricati

3

Il file ottiene la spazzatura raccolta e quindi chiusa. Il GC determina quando viene chiuso, non tu. Ovviamente, questa non è una pratica consigliata perché potresti toccare il limite di gestione dei file aperti se non chiudi i file non appena finisci di usarli. E se all'interno di quel fortuo ciclo, apri più file e li lasci persistere?


Ma se si aprissero altri file all'interno di quello per il ciclo, sarebbe comunque possibile che vi siano più di un file aperti contemporaneamente indipendentemente dal fatto che si chiuda esplicitamente uno di essi o meno. Stai dicendo che il file non è necessariamente garbage collection non appena esce dal campo di applicazione, quindi sarebbe chiuso prima se fatto esplicitamente? Che dire di quando si verifica un'eccezione (quando si utilizza con / try-finally anziché non farlo)?
user553702

1
In CPython, il conteggio dei riferimenti farà sì che venga raccolto dopo l' foristruzione: non dovrai attendere la prossima esecuzione della garbage collection.
AGF

3

Ciao È molto importante chiudere il descrittore di file in una situazione quando si intende utilizzarne il contenuto nello stesso script Python. Oggi stesso mi rendo conto dopo tanto tempo di debugging. Il motivo è che il contenuto verrà modificato / rimosso / salvato solo dopo aver chiuso il descrittore di file e le modifiche sono interessate al file!

Supponiamo quindi di avere una situazione in cui scrivi il contenuto in un nuovo file e quindi senza chiudere fd stai usando quel file (non fd) in un altro comando shell che legge il suo contenuto. In questa situazione non otterrai i contenuti per il comando shell come previsto e se provi a eseguire il debug non riesci a trovare facilmente il bug. puoi anche leggere di più nel mio blog http://magnificentzps.blogspot.in/2014/04/importance-of-closing-file-descriptor.html


1

Durante il processo di I / O, i dati vengono bufferizzati: ciò significa che vengono conservati in una posizione temporanea prima di essere scritti nel file.

Python non scarica il buffer, ovvero scrive i dati nel file, fino a quando non si è sicuri di aver finito di scrivere. Un modo per farlo è chiudere il file.

Se si scrive su un file senza chiuderlo, i dati non verranno inseriti nel file di destinazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.