Risposte:
La risposta a questa domanda dipende in qualche modo dalla particolare implementazione di Python.
Per capire di cosa si tratta, presta particolare attenzione file
all'oggetto reale . Nel tuo codice, quell'oggetto è menzionato una sola volta, in un'espressione, e diventa inaccessibile immediatamente dopo il read()
ritorno della chiamata.
Ciò significa che l'oggetto file è immondizia. L'unica domanda rimasta è "Quando il garbage collector raccoglierà l'oggetto file?".
in CPython, che utilizza un contatore di riferimento, questo tipo di immondizia viene notato immediatamente e quindi verrà raccolto immediatamente. Questo non è generalmente vero per altre implementazioni di Python.
Una soluzione migliore, per assicurarsi che il file sia chiuso, è questo modello:
with open('Path/to/file', 'r') as content_file:
content = content_file.read()
che chiuderà sempre il file immediatamente dopo la fine del blocco; anche se si verifica un'eccezione.
Modifica: per aggiungere un punto più preciso:
A parte questo file.__exit__()
, che viene chiamato "automaticamente" in un'impostazione del with
gestore di contesto, l'unico altro modo che file.close()
viene chiamato automaticamente (ovvero, oltre a chiamarlo esplicitamente da solo) è tramite file.__del__()
. Questo ci porta alla domanda su quando __del__()
viene chiamato?
Un programma scritto correttamente non può presumere che i finalizzatori verranno mai eseguiti in qualsiasi momento prima della fine del programma.
- https://devblogs.microsoft.com/oldnewthing/20100809-00/?p=13203
In particolare:
Gli oggetti non vengono mai esplicitamente distrutti; tuttavia, quando diventano irraggiungibili, possono essere raccolti nella spazzatura. Un'implementazione può posticipare la garbage collection o ometterla del tutto - è una questione di qualità dell'implementazione il modo in cui la garbage collection viene implementata, purché non vengano raccolti oggetti che siano ancora raggiungibili.
[...]
CPython attualmente utilizza uno schema di conteggio dei riferimenti con il rilevamento (facoltativo) ritardato di immondizia collegata ciclicamente, che raccoglie la maggior parte degli oggetti non appena diventano irraggiungibili, ma non è garantito che raccolga immondizia contenente riferimenti circolari.
- https://docs.python.org/3.5/reference/datamodel.html#objects-values-and-types
(Enfasi mia)
ma come suggerisce, altre implementazioni possono avere altri comportamenti. Ad esempio, PyPy ha 6 diverse implementazioni di garbage collection !
__exit__()
in questi casi sembra un difetto di progettazione.
try
/ finally
fiddly e l'utile molto comune dei gestori di cleanup che with
risolve. La differenza tra "chiusura esplicita" e "gestione con with
" è che il gestore di uscita viene chiamato anche se viene generata un'eccezione. Si potrebbe mettere il close()
in una finally
clausola di, ma che non è molto diverso da utilizzare with
, invece, un po 'Messier (3 linee extra invece di 1), e un po' più difficile per ottenere appena a destra.
with foo() as f: [...]
è fondamentalmente la stessa f = foo()
, f.__enter__()
[...] e f.__exit__()
con le eccezioni gestite , in modo che __exit__
si chiama sempre. Quindi il file viene sempre chiuso.
Puoi usare pathlib .
Per Python 3.5 e versioni successive:
from pathlib import Path
contents = Path(file_path).read_text()
Per le versioni precedenti di Python utilizzare pathlib2 :
$ pip install pathlib2
Poi:
from pathlib2 import Path
contents = Path(file_path).read_text()
Questa è l' read_text
implementazione effettiva :
def read_text(self, encoding=None, errors=None):
"""
Open the file in text mode, read it, and close the file.
"""
with self.open(mode='r', encoding=encoding, errors=errors) as f:
return f.read()
Invece di recuperare il contenuto del file come singola stringa, può essere utile archiviare il contenuto come un elenco di tutte le righe che comprende il file :
with open('Path/to/file', 'r') as content_file:
content_list = content_file.read().strip().split("\n")
Come si può vedere, è necessario aggiungere i metodi concatenati .strip().split("\n")
alla risposta principale in questo thread .
Qui, .strip()
rimuove solo gli spazi bianchi e i caratteri di nuova riga alla fine dell'intera stringa di file e .split("\n")
produce l'elenco effettivo dividendo l'intera stringa di file in corrispondenza di ogni carattere di nuova riga \ n .
Inoltre, in questo modo l'intero contenuto del file può essere archiviato in una variabile, il che potrebbe essere desiderato in alcuni casi, invece di passare in rassegna il file riga per riga, come sottolineato in questa risposta precedente .