it-swarm.it

Lettura dell'intero file in Python

Se leggi un intero file con content = open('Path/to/file', 'r').read() il manico del file rimane aperto fino allo scadere dello script? C'è un metodo più conciso per leggere un intero file?

300
tMC

la risposta a questa domanda dipende in qualche modo dalla particolare implementazione di Python.

Per capire di cosa si tratta, presta particolare attenzione all'attuale oggetto file. Nel tuo codice, quell'oggetto viene menzionato solo una volta, in un'espressione, e diventa inaccessibile immediatamente dopo il ritorno della chiamata read().

Ciò significa che l'oggetto file è spazzatura. L'unica domanda rimanente è "Quando il garbage collector raccoglierà l'oggetto file?".

in CPython, che usa un contatore di riferimento, questo tipo di garbage viene notato immediatamente e quindi verrà raccolto immediatamente. Questo in genere non è vero per altre implementazioni di Python.

Una soluzione migliore, per assicurarsi che il file sia chiuso, è questo schema:

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 mettere un punto più preciso su di esso:

A parte file.__exit__(), che viene chiamato "automaticamente" in un'impostazione del gestore di contesto with, l'unico altro modo in cui file.close() viene chiamato automaticamente (ovvero, oltre a chiamarlo esplicitamente da solo), è tramite file.__del__(). Questo ci porta alla domanda di quando viene chiamata __del__()?

Un programma scritto correttamente non può presumere che i finalizzatori verranno mai eseguiti in qualsiasi momento prima della chiusura del programma.

- https://devblogs.Microsoft.com/oldnewthing/20100809-00/?p=13203

In particolare:

Gli oggetti non vengono mai distrutti esplicitamente; tuttavia, quando diventano irraggiungibili, possono essere raccolti dalla spazzatura. Un'implementazione può posticipare la garbage collection o ometterla del tutto - è una questione di qualità di implementazione come viene implementata la garbage collection, purché non siano raccolti oggetti che sono ancora raggiungibili.

[...]

CPython utilizza attualmente uno schema di conteggio dei riferimenti con (facoltativo) rilevamento ritardato della spazzatura collegata ciclicamente, che raccoglie la maggior parte degli oggetti non appena diventano irraggiungibili, ma non è garantito il recupero di rifiuti contenenti riferimenti circolari.

- https://docs.python.org/3.5/reference/datamodel.html#objects-values-and-types

(Enfasi mia)

ma come suggerisce, altre implementazioni potrebbero avere altri comportamenti. Ad esempio, PyPy ha 6 diverse implementazioni di Garbage Collection !

È possibile utilizzare pathlib .

Per Python 3.5 e versioni successive:

from pathlib import Path
contents = Path(file_path).read_text()

Per versioni inferiori di Python usa pathlib2 :

$ pip install pathlib2

Poi:

from pathlib2 import Path
contents = Path(file_path).read_text()

Questa è l'implementazione read_texteffettiva :

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()
63
Eyal Levin