I file sono solo stringhe con un percorso
Prima o poi la maggior parte dei programmi deve leggere o scrivere un file: configurazioni, dati degli utenti, log, esportazioni CSV, piccole cache. Python rende tutto semplice con un'unica funzione integrata, open(), più un blocco with per assicurarsi che tutto venga chiuso in modo pulito.
Vediamo i casi più comuni.
Leggere un file intero
La lettura più semplice:
with open("notes.txt") as f:
contents = f.read()
print(contents)
open("notes.txt") apre il file in lettura (il comportamento predefinito). Il blocco with fa sì che Python chiuda il file quando esci dal blocco, anche se viene sollevata un'eccezione. Una volta chiuso, non puoi più usare f; il testo si trova in contents.
contents è un'unica stringa che contiene l'intero file. Va bene per file piccoli; pessima idea per un log da 2 GB.
Leggere riga per riga
Per i file più grandi, scorrili invece di caricare tutto in memoria:
with open("big.log") as f:
for line in f:
if "ERROR" in line:
print(line.strip())
Ogni iterazione restituisce una riga compreso il carattere di a capo finale: ecco perché .strip() compare così spesso. Se vuoi una lista di righe, f.readlines() fa proprio questo, ma di solito l'iterazione diretta è quello che ti serve.
Scrivere un file
Per scrivere, passa la modalità come secondo argomento:
with open("output.txt", "w") as f:
f.write("first line\n")
f.write("second line\n")
Due cose da notare:
"w"sovrascrive. Seoutput.txtesiste già, il suo contenuto sparisce nel momento in cui viene eseguitoopen.- Gli a capo li devi aggiungere tu.
f.write("hello")scrive esattamente quei cinque caratteri, senza a capo finale.
Per aggiungere invece di sovrascrivere:
with open("output.txt", "a") as f:
f.write("another line\n")
Puoi anche passare più righe in una volta con writelines:
lines = ["a\n", "b\n", "c\n"]
with open("letters.txt", "w") as f:
f.writelines(lines)
Stessa regola: gli a capo li metti tu.
print su un file
print ha un argomento file, un modo facile per scrivere senza aggiungere gli a capo a mano:
with open("log.txt", "w") as f:
print("started", file=f)
print("finished", file=f)
Ogni print scrive i suoi argomenti più un a capo finale. Per un output informale, spesso è la forma più comoda.
Modalità testo e modalità binaria
Per impostazione predefinita, open lavora in modalità testo. Python decodifica i byte in stringhe (usando UTF-8 per impostazione predefinita sulle piattaforme moderne) e gestisce la conversione degli a capo.
Per immagini, PDF, file compilati o qualsiasi cosa non sia testo, apri in modalità binaria aggiungendo "b" alla modalità:
with open("image.png", "rb") as f:
data = f.read()
print(len(data)) # numero di byte
with open("image_copy.png", "wb") as f:
f.write(data)
In modalità binaria ottieni oggetti bytes invece di str, e Python non tocca i fine riga.
Specificare la codifica
Per i file di testo, specifica esplicitamente la codifica. Nel 2026 UTF-8 è quasi sempre la scelta giusta:
with open("notes.txt", encoding="utf-8") as f:
contents = f.read()
Se hai a che fare con vecchi file di un ambiente solo Windows, potresti trovare anche cp1252 o latin-1. Se sbagli ottieni caratteri incomprensibili o un UnicodeDecodeError.
pathlib: il modo moderno di gestire i percorsi
Il modulo pathlib della libreria standard ti offre un'API più comoda delle semplici stringhe:
from pathlib import Path
path = Path("notes.txt")
# Lettura e scrittura semplici.
contents = path.read_text(encoding="utf-8")
path.write_text("new contents\n", encoding="utf-8")
# Costruisci percorsi senza preoccuparti di / o \.
data_dir = Path("data")
log_path = data_dir / "today.log"
print(log_path)
print(log_path.exists())
print(log_path.suffix) # ".log"
print(log_path.stem) # "today"
print(log_path.parent) # "data"
Path.read_text() e write_text() sono scorciatoie per lo schema with open(...) as f quando vuoi solo leggere e scrivere tutto in una volta. Per scorrere riga per riga usi ancora open o path.open().
Un piccolo esempio completo
Leggere una lista di elementi da un file, filtrarli e scrivere il risultato in un altro file:
from pathlib import Path
source = Path("items.txt")
destination = Path("filtered.txt")
items = source.read_text().splitlines()
kept = [item for item in items if item and not item.startswith("#")]
destination.write_text("\n".join(kept) + "\n")
print(f"Kept {len(kept)} items out of {len(items)}")
splitlines() è il compagno di join orientato alle righe. Divide sui caratteri di a capo senza conservarli: comodo quando poi rimetterai insieme i pezzi comunque.
Quando qualcosa va storto
Aprire un file che non esiste solleva FileNotFoundError. Provare a leggere un file per cui non hai i permessi solleva PermissionError. Sono entrambe sottoclassi di OSError, che a sua volta è una sottoclasse di Exception: nella prossima pagina vedremo come gestire bene le eccezioni.
Per ora, un'anteprima veloce di come appare la gestione degli errori:
from pathlib import Path
path = Path("maybe.txt")
try:
contents = path.read_text()
except FileNotFoundError:
print("File doesn't exist - starting fresh.")
contents = ""
print(repr(contents))
Abitudini fondamentali
- Usa sempre
with open(...)invece di un sempliceopencon chiusura manuale. - Passa sempre
encoding=per i file di testo; UTF-8 come scelta predefinita. - Scorri i file grandi riga per riga; non leggerli interi con
.read(). - Per i percorsi e le letture e scritture più comuni, usa
pathlib: ti risparmierà un sacco di acrobazie con le stringhe.
Domande frequenti
Come leggo un file in Python?
Usa open() con l'istruzione with, che chiude il file in automatico quando hai finito. with open('file.txt') as f: contents = f.read() legge l'intero file in una stringa. Per leggerlo riga per riga, fai un ciclo direttamente sull'oggetto file: for line in f:.
Qual è la differenza tra le modalità di apertura 'r', 'w' e 'a'?
'r' è la lettura (il valore predefinito). 'w' è la scrittura: crea il file, o lo svuota se esiste già. 'a' è l'aggiunta: scrive in fondo al file senza cancellare quello che c'è. Aggiungi 'b' per la modalità binaria o '+' per lettura e scrittura insieme.
Perché usare with open invece del semplice open?
with open invece del semplice open?L'istruzione with garantisce che il file venga chiuso anche se a metà si verifica un errore. Senza with devi chiamare tu .close() e ricordarti di farlo anche nei percorsi di errore. with è più sicuro e richiede meno codice.