Menu

Gestione dei file in Python: leggere, scrivere e aggiungere in sicurezza

Come leggere e scrivere file in Python: l'istruzione with, modalità testo e binaria, e la moderna e più sicura API basata sui percorsi.

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. Se output.txt esiste già, il suo contenuto sparisce nel momento in cui viene eseguito open.
  • 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 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 semplice open con 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?

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.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA