Gestione dei file in Python: una guida completa
Impara la gestione dei file in Python: apri i file in ogni modalità, leggi e scrivi dati, usa pathlib, gestisci gli errori e naviga nelle posizioni del file.
La gestione dei file consente ai tuoi programmi di memorizzare i dati in modo permanente e recuperarli in seguito. Questo capitolo spiega ogni operazione comune sui file in Python — apertura dei file in diverse modalità, lettura e scrittura dei dati, navigazione all'interno di un file, specificazione della codifica dei caratteri e gestione degli errori che emergono nel codice reale.
La funzione open()
Ogni operazione sui file in Python inizia con open(). Restituisce un oggetto file che espone metodi per leggere, scrivere e posizionarsi all'interno del file.
file_object = open(file, mode="r", encoding=None)file— il percorso del file (una string o un oggettopathlib.Path).mode— come aprire il file (vedi la tabella qui sotto).encoding— la codifica del testo, ad es."utf-8". Specificala sempre per i file di testo in modo che il codice funzioni allo stesso modo su qualsiasi sistema operativo.
Modalità di apertura dei file
| Modalità | Significato | Crea il file? | Tronca il file esistente? |
|---|---|---|---|
"r" | Lettura (predefinita) | No | No |
"w" | Scrittura | Sì | Sì |
"a" | Aggiunta | Sì | No |
"x" | Creazione esclusiva | Fallisce se il file esiste | — |
"r+" | Lettura e scrittura | No | No |
"b" | Binario (combinare con le precedenti, es. "rb") | — | — |
"t" | Testo (predefinito, combinare con le precedenti, es. "rt") | — | — |
Usa sempre with per aprire i file
L'istruzione with (un context manager) garantisce che il file venga chiuso quando il blocco termina — anche se viene sollevata un'eccezione. Questo previene le perdite di risorse e assicura che le scritture bufferizzate vengano scaricate su disco.
Apri un file in modo sicuro con with
with open("notes.txt", "r", encoding="utf-8") as f:
contents = f.read()
# File is automatically closed hereChiamare open() senza with e dimenticare file.close() è una fonte comune di corruzione dei dati ed errori "troppi file aperti" nei programmi a lunga esecuzione.
Lettura dei file
Python fornisce diversi modi per leggere il contenuto di un file.
Leggi l'intero file con read()
read() restituisce il contenuto completo del file come singola string.
Leggi un intero file
with open("notes.txt", "r", encoding="utf-8") as f:
content = f.read()
print(content)Per i file di grandi dimensioni, questo carica tutto in memoria in una volta sola, il che va bene per i file piccoli ma è inefficiente per i log da diversi gigabyte.
Leggi un numero fisso di caratteri
Passa un intero a read(n) per leggere al massimo n caratteri.
Leggi i primi 20 caratteri
with open("notes.txt", "r", encoding="utf-8") as f:
chunk = f.read(20)
print(repr(chunk))Leggi una riga alla volta con readline()
readline() restituisce la riga successiva incluso il \n finale, oppure una string vuota alla fine del file.
Leggi 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()Itera sulle righe (il metodo più pythonic)
Iterare direttamente su un oggetto file è l'approccio più efficiente in termini di memoria per la lettura riga per riga.
Itera sulle righe
with open("notes.txt", "r", encoding="utf-8") as f:
for line in f:
print(line, end="")Leggi tutte le righe in una lista con readlines()
readlines() restituisce una lista in cui ogni elemento è una riga (con il carattere di nuova riga incluso).
Leggi 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(len(lines)) # total number of linesUsa readlines() quando hai bisogno di accesso casuale a righe specifiche tramite indice. Per l'elaborazione sequenziale, preferisci il pattern for line in f.
Scrittura dei file
Modalità scrittura ("w")
La modalità scrittura crea il file se non esiste e lo tronca (svuota) se esiste.
Scrivi testo in un file
with open("output.txt", "w", encoding="utf-8") as f:
f.write("Line one\n")
f.write("Line two\n")Scrivi più righe con writelines()
writelines() accetta un iterabile di string. Non aggiunge automaticamente caratteri di nuova riga.
Scrivi una lista di righe
lines = ["apple\n", "banana\n", "cherry\n"]
with open("fruits.txt", "w", encoding="utf-8") as f:
f.writelines(lines)Modalità aggiunta ("a")
La modalità aggiunta sposta la posizione di scrittura alla fine del file prima di ogni scrittura, quindi il contenuto esistente non viene mai sovrascritto.
Aggiungi una voce di log
import datetime
entry = f"{datetime.date.today()} — task complete\n"
with open("log.txt", "a", encoding="utf-8") as f:
f.write(entry)Ogni volta che questo script viene eseguito aggiunge una nuova riga a log.txt senza toccare le voci precedenti.
Modalità creazione esclusiva ("x")
Usa "x" quando vuoi creare un nuovo file e garantire di non sovrascrivere uno esistente. Python solleva FileExistsError se il file esiste già.
Crea un file solo se non esiste
try:
with open("config.txt", "x", encoding="utf-8") as f:
f.write("[settings]\n")
except FileExistsError:
print("config.txt already exists — not overwriting.")Posizioni nel file: seek() e tell()
Gli oggetti file mantengono un puntatore di posizione interno che avanza man mano che leggi o scrivi. Puoi ispezionare e modificare questo puntatore.
tell()— restituisce la posizione in byte corrente.seek(offset, whence=0)— sposta il puntatore.whence=0(predefinito) è dall'inizio,1è dalla posizione corrente,2è dalla fine.
Torna all'inizio con seek(0)
with open("notes.txt", "r", encoding="utf-8") as f:
first_pass = f.read()
f.seek(0) # go back to the start
second_pass = f.read()
print(first_pass == second_pass) # Trueseek() è particolarmente utile nella modalità "r+" (lettura e scrittura) dove potresti leggere una sezione e poi sovrascriverla nella stessa chiamata di apertura.
Lavorare con i file binari
Apri un file in modalità binaria aggiungendo "b" alla string della modalità ("rb", "wb", "ab"). La modalità binaria fornisce byte grezzi invece di string, il che è essenziale per immagini, audio, archivi compressi e altri dati non testuali.
Copia un file in modalità binaria
with open("photo.jpg", "rb") as src:
data = src.read()
with open("photo_backup.jpg", "wb") as dst:
dst.write(data)Non specificare encoding quando si usa la modalità binaria — Python solleverà un ValueError se ci provi.
Gestione degli errori
Le operazioni sui file possono fallire in modi prevedibili. Avvolgerle in blocchi try/except rende i tuoi script robusti.
Gestisci gli errori comuni sui file
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 OSError as e:
print(f"OS error: {e}")Eccezioni comuni che incontrerai:
| Eccezione | Quando si verifica |
|---|---|
FileNotFoundError | Lettura di un file che non esiste |
FileExistsError | Creazione di un file con modalità "x" quando esiste già |
PermissionError | Mancanza di permessi di lettura/scrittura |
IsADirectoryError | Tentativo di aprire una directory come file |
UnicodeDecodeError | I byte del file non corrispondono alla codifica specificata |
L'alternativa moderna con pathlib
Python 3.4 ha introdotto pathlib.Path, un approccio orientato agli oggetti ai percorsi del file system. Gli oggetti Path funzionano perfettamente con open() ed espongono anche i propri metodi di convenienza read_text() / write_text().
Leggi un file con pathlib
from pathlib import Path
content = Path("notes.txt").read_text(encoding="utf-8")
print(content)Scrivi un file con pathlib
from pathlib import Path
Path("output.txt").write_text("Hello, world!\n", encoding="utf-8")read_text() e write_text() aprono e chiudono il file per te, rendendo le letture e le scritture in un'unica operazione molto concise. Usa open() con un blocco with quando hai bisogno di un controllo più fine — ad esempio, leggere un file in blocchi o usare seek().
Rinominare e spostare i file
Per rinominare o spostare un file, usa os.rename() per una ridenominazione sullo stesso filesystem, o shutil.move() quando devi spostare tra filesystem diversi.
Rinomina un file con os.rename()
import os
os.rename("old_name.txt", "new_name.txt")Sposta un file con shutil.move()
import shutil
shutil.move("report.txt", "archive/report.txt")shutil.move() funziona anche quando sorgente e destinazione si trovano su unità diverse; os.rename() in quel caso solleva OSError.
Verificare se un file esiste
Prima di aprire un file per la lettura, potresti voler confermare che esiste. Usa os.path.exists() o l'equivalente con pathlib.
Verifica l'esistenza con os.path
import os
if os.path.exists("data.txt"):
print("File found.")
else:
print("File not found.")Verifica l'esistenza con pathlib
from pathlib import Path
p = Path("data.txt")
if p.exists():
print("File found.")Nota che os.path.exists() e Path.exists() possono restituire risultati non aggiornati in programmi multi-thread o multi-processo. In questi casi, è preferibile aprire direttamente il file con open() e intercettare FileNotFoundError.
Riepilogo delle funzioni principali
| Operazione | Approccio con os / shutil | Approccio con pathlib |
|---|---|---|
| Apri e leggi | open(path, "r") | Path(path).read_text() |
| Apri e scrivi | open(path, "w") | Path(path).write_text() |
| Verifica esistenza | os.path.exists(path) | Path(path).exists() |
| Rinomina | os.rename(src, dst) | Path(src).rename(dst) |
| Sposta | shutil.move(src, dst) | Path(src).rename(dst) (stesso FS) |
| Elimina | os.remove(path) | Path(path).unlink() |
Capitoli correlati
- Lettura di file in Python — approfondimento su ogni tecnica di lettura
- Scrittura e creazione di file in Python — scrittura, creazione e best practice
- Eliminazione di file in Python — eliminazione sicura di file e directory
- Try Except in Python — gestione delle eccezioni in Python
- Istruzione With in Python — come funzionano i context manager