Leggere File in Python – Guida Completa
Impara tutti i modi per leggere file in Python: read(), readline(), readlines(), iterazione, modalità binaria, encoding e pathlib.
Leggere file è una delle operazioni più comuni in Python — che si tratti di caricare configurazioni, elaborare log, importare dati CSV o leggere risorse binarie. Questo capitolo tratta tutti i metodi che Python offre per leggere il contenuto di un file: dalla più semplice chiamata read() all'iterazione riga per riga efficiente in termini di memoria, alla modalità binaria, alla gestione dell'encoding, al controllo della posizione nel file e alla moderna API pathlib.
Aprire un File in Lettura
Ogni operazione su file inizia con la funzione built-in open(). Per aprire un file in modalità lettura, usa la stringa di modalità "r" (che è quella predefinita quando non viene specificata alcuna modalità):
file_object = open("notes.txt", "r", encoding="utf-8")"r"— apre in lettura; sollevaFileNotFoundErrorse il file non esiste.encoding="utf-8"— specifica sempre la codifica dei caratteri per i file di testo in modo che il tuo codice funzioni in modo identico su Windows, macOS e Linux.
Usa Sempre un Blocco with
Il modo più sicuro per aprire un file è all'interno di un'istruzione with. Python chiude automaticamente il file quando il blocco termina — anche se si verifica un'eccezione — il che previene perdite di risorse e garantisce che i dati in buffer vengano scritti.
with open("notes.txt", "r", encoding="utf-8") as f:
contents = f.read()
# File is automatically closed hereChiamare open() al di fuori di un blocco with e dimenticare file.close() è una fonte frequente di errori "too many open files" negli script a lunga esecuzione.
Leggere l'Intero File con read()
read() restituisce il contenuto completo del file come una singola string.
Leggere un intero file in una volta
with open("notes.txt", "r", encoding="utf-8") as f:
contents = f.read()
print(contents)Usa read() quando:
- Il file è abbastanza piccolo da stare comodamente in memoria.
- Hai bisogno del testo completo come una singola string (ad es. per il parsing o la ricerca).
Per file che potrebbero essere grandi (log, dump di dati), preferisci gli approcci riga per riga descritti di seguito.
Leggere un Numero Fisso di Caratteri
Passa un intero n a read(n) per leggere al massimo n caratteri dalla posizione corrente. Le chiamate successive a read(n) continuano da dove si era fermata l'ultima lettura.
Leggere i primi 50 caratteri
with open("notes.txt", "r", encoding="utf-8") as f:
first_chunk = f.read(50)
second_chunk = f.read(50)
print(repr(first_chunk))
print(repr(second_chunk))Questo approccio a blocchi è utile quando vuoi visualizzare un'anteprima di un file o elaborarlo in pezzi di dimensione fissa senza caricare tutto in memoria.
Leggere una Riga alla Volta con readline()
readline() legge una riga dal file, incluso il carattere di a capo finale \n. Restituisce una string vuota "" quando viene raggiunta la fine del file, il che rende facile eseguire un ciclo fino all'EOF.
Leggere un file riga per riga con readline()
with open("notes.txt", "r", encoding="utf-8") as f:
line = f.readline()
while line:
print(line, end="") # line already contains '\n'
line = f.readline()L'argomento end="" in print() previene la comparsa di una doppia riga vuota (una dalla riga del file e una dal comportamento predefinito di print).
readline() è utile quando devi elaborare una riga di intestazione in modo diverso dal resto, o quando vuoi interrompere la lettura a metà del file in base a una condizione.
Iterazione sulle Righe (il Modo più Pythonico)
Iterare direttamente su un oggetto file è il modo più idiomatico ed efficiente in termini di memoria per elaborare un file di testo riga per riga. Python legge una riga alla volta senza caricare l'intero file in memoria.
Iterare sulle righe con un ciclo for
with open("notes.txt", "r", encoding="utf-8") as f:
for line in f:
print(line, end="")Questo pattern è preferibile rispetto a read() + split("\n") e rispetto alla chiamata di readline() in un ciclo while, perché è più breve e gestisce correttamente tutti i casi limite (inclusi i file che non terminano con una riga vuota).
Cercare un pattern durante l'iterazione
with open("server.log", "r", encoding="utf-8") as f:
for line in f:
if "ERROR" in line:
print(line, end="")Leggere Tutte le Righe in una Lista con readlines()
readlines() restituisce una lista in cui ogni elemento è una riga del file (con il carattere di a capo incluso). Questo carica l'intero file in memoria.
Leggere tutte le righe in una lista
with open("notes.txt", "r", encoding="utf-8") as f:
lines = f.readlines()
print(lines[0]) # first line
print(lines[-1]) # last line
print(len(lines)) # total number of linesUsa readlines() quando hai bisogno di accesso casuale a righe specifiche tramite indice. Per l'elaborazione sequenziale dall'alto verso il basso, il pattern for line in f è più efficiente in termini di memoria.
Rimuovere i Caratteri di A Capo
Le righe restituite da readline(), readlines() e dall'iterazione con il ciclo for includono tutte il \n finale. Usa .strip() o .rstrip("\n") per rimuoverlo:
with open("notes.txt", "r", encoding="utf-8") as f:
lines = [line.rstrip("\n") for line in f]
print(lines) # ['Line one', 'Line two', 'Line three']Scegliere il Metodo di Lettura Giusto
| Metodo | Restituisce | Carica l'intero file? | Ideale per |
|---|---|---|---|
f.read() | str | Sì | File piccoli, parsing di testo completo |
f.read(n) | str | No (a blocchi) | Streaming a dimensione fissa |
f.readline() | str | No | Interruzioni condizionali riga per riga |
for line in f | str (uno per iterazione) | No | Elaborazione sequenziale delle righe |
f.readlines() | list[str] | Sì | Accesso casuale per indice alle righe |
Posizione nel File: tell() e seek()
Ogni oggetto file aperto mantiene un puntatore di posizione interno che avanza durante la lettura. Due metodi consentono di ispezionarlo e controllarlo:
tell()— restituisce l'offset in byte corrente dall'inizio del file.seek(offset, whence=0)— sposta il puntatore. Conwhence=0(predefinito) l'offset è dall'inizio;whence=1è dalla posizione corrente;whence=2è dalla fine.
Leggere un file due volte usando seek(0)
with open("notes.txt", "r", encoding="utf-8") as f:
first_pass = f.read()
print(f"Position after first read: {f.tell()}")
f.seek(0) # rewind to the beginning
second_pass = f.read()
print(first_pass == second_pass) # Trueseek() è particolarmente utile in modalità "r+" (lettura-scrittura), dove potresti leggere una sezione di un file e poi sovrascrivere una parte specifica nella stessa chiamata open().
Gestione degli Errori durante la Lettura
Uno script ben scritto anticipa sempre i modi in cui una lettura di file può fallire.
Gestire gli errori di lettura più comuni
try:
with open("data.txt", "r", encoding="utf-8") as f:
content = f.read()
except FileNotFoundError:
print("Error: the file does not exist.")
except PermissionError:
print("Error: you do not have permission to read this file.")
except UnicodeDecodeError:
print("Error: the file contains bytes that are not valid UTF-8.")
except OSError as e:
print(f"OS error: {e}")Eccezioni comuni che incontrerai:
| Eccezione | Quando si verifica |
|---|---|
FileNotFoundError | Il percorso non punta a un file esistente |
PermissionError | Il processo non ha il permesso di lettura |
IsADirectoryError | Il percorso punta a una directory, non a un file |
UnicodeDecodeError | I byte del file non corrispondono all'encoding specificato |
Vedi Python Try Except per una guida completa alla gestione delle eccezioni.
Codifica dei Caratteri
Quando Python apre un file in modalità testo, deve sapere come convertire i byte grezzi in caratteri. Passa sempre encoding= esplicitamente anziché affidarti al valore predefinito della piattaforma, che differisce tra Windows (cp1252) e la maggior parte dei sistemi Unix (utf-8).
Valori di encoding comuni:
| Encoding | Usa quando |
|---|---|
"utf-8" | File moderni, contenuto web, la maggior parte dei progetti Python |
"utf-8-sig" | File UTF-8 creati da strumenti Windows che antepongono un BOM |
"latin-1" | File Western-European legacy |
"cp1252" | File di testo ANSI di Windows |
Rilevare o ignorare i problemi di encoding:
Se non sei sicuro dell'encoding di un file, puoi dire a Python di sostituire i byte non decodificabili con un segnaposto anziché sollevare un errore:
with open("mystery.txt", "r", encoding="utf-8", errors="replace") as f:
content = f.read()Altri valori per errors includono "ignore" (ignora silenziosamente i byte non validi) e "strict" (predefinito — solleva UnicodeDecodeError).
Leggere File Binari
Apri un file in modalità binaria aggiungendo "b" alla stringa di modalità ("rb"). La modalità binaria restituisce oggetti bytes grezzi anziché string, il che è corretto per immagini, audio, archivi compressi, eseguibili e qualsiasi dato non testuale.
Leggere un file binario
with open("photo.jpg", "rb") as f:
data = f.read()
print(type(data)) # <class 'bytes'>
print(len(data)) # size in bytesCopiare un file binario
with open("photo.jpg", "rb") as src:
data = src.read()
with open("photo_backup.jpg", "wb") as dst:
dst.write(data)Non specificare encoding in modalità binaria — Python solleva ValueError se ci provi.
Leggere File di Grandi Dimensioni in Modo Efficiente
Caricare un file da diversi gigabyte con read() può esaurire la memoria di sistema. Le soluzioni sono:
Iterazione riga per riga (file di testo)
with open("huge_log.txt", "r", encoding="utf-8") as f:
for line in f:
process(line) # only one line in memory at a timeBlocchi di dimensione fissa (file binari)
CHUNK_SIZE = 65536 # 64 KB
with open("large_file.bin", "rb") as f:
while True:
chunk = f.read(CHUNK_SIZE)
if not chunk:
break
process(chunk)Entrambi i pattern mantengono l'utilizzo della memoria costante indipendentemente dalla dimensione del file.
Leggere File con pathlib
Python 3.4 ha introdotto pathlib.Path, che fornisce un'interfaccia orientata agli oggetti per i percorsi del file system. Per letture e scritture semplici in un'unica operazione, gli oggetti Path sono più concisi di open().
Leggere testo con Path.read_text()
from pathlib import Path
content = Path("notes.txt").read_text(encoding="utf-8")
print(content)Leggere byte con Path.read_bytes()
from pathlib import Path
data = Path("photo.jpg").read_bytes()
print(len(data)) # file size in bytesread_text() e read_bytes() aprono il file, ne leggono l'intero contenuto e lo chiudono in un'unica chiamata. Usali per file piccoli quando hai solo bisogno del contenuto. Usa open() con un blocco with quando hai bisogno dell'iterazione riga per riga, della lettura a blocchi, di seek() o di qualsiasi altro controllo granulare.
Verificare che un File Esista Prima di Leggerlo
from pathlib import Path
p = Path("data.txt")
if p.exists() and p.is_file():
content = p.read_text(encoding="utf-8")
else:
print("File not found.")Nota: p.exists() può restituire un risultato non aggiornato nel codice multi-thread. In questi casi è più sicuro tentare la lettura e intercettare FileNotFoundError.
Esempio Pratico: Leggere un Semplice File di Configurazione
Molti script leggono un file di configurazione in testo semplice che memorizza una coppia key=value per riga. Ecco un esempio completo e funzionante:
Analizzare un file di configurazione key=value
from pathlib import Path
def load_config(path):
config = {}
with open(path, "r", encoding="utf-8") as f:
for line in f:
line = line.strip()
if not line or line.startswith("#"):
continue # skip blank lines and comments
key, _, value = line.partition("=")
config[key.strip()] = value.strip()
return config
# Example config.txt contents:
# host = localhost
# port = 8080
# debug = true
config = load_config("config.txt")
# config == {'host': 'localhost', 'port': '8080', 'debug': 'true'}str.partition("=") divide solo sul primo =, quindi i valori che contengono = (come le string Base64) vengono gestiti correttamente.
Capitoli Correlati
- Python File Handling — modalità di apertura, istruzione
with,seek(), file binari, panoramica di pathlib - Python Write / Create Files — scrittura, creazione e aggiunta di contenuto ai file
- Python Delete Files — eliminazione sicura di file e directory
- Python Try Except — gestione delle eccezioni in Python
- Python CSV — lettura e scrittura di file CSV con il modulo
csv