Python & AI Tutorials Logo
Programmazione Python

27. Leggere e scrivere file

Finora, tutti i dati nei nostri programmi sono stati temporanei—memorizzati in variabili che scompaiono quando il programma termina. Per creare programmi che ricordino informazioni tra un’esecuzione e l’altra, dobbiamo lavorare con i file. I file ci permettono di salvare dati su disco e rileggerli in seguito, abilitando qualsiasi cosa, dalle impostazioni di configurazione all’archiviazione dei dati utente.

In questo capitolo, imparerai come leggere e scrivere su file di testo in Python. Inizieremo comprendendo i percorsi dei file e come Python li individua, poi passeremo ad aprire, leggere, scrivere e chiudere correttamente i file. Imparerai le diverse modalità dei file, la codifica del testo e come gestire gli errori comuni che si verificano durante le operazioni sui file.

27.1) Percorsi dei file e directory di lavoro corrente

Prima di poter lavorare con i file, dobbiamo capire come Python li individua nel file system del tuo computer.

27.1.1) Comprendere i percorsi dei file

Un percorso del file è l’indirizzo di un file sul tuo computer. Dice a Python esattamente dove trovare un file. Esistono due tipi di percorsi:

I percorsi assoluti specificano la posizione completa a partire dalla radice del file system:

  • Windows: C:\Users\Alice\Documents\data.txt
  • macOS/Linux: /home/alice/documents/data.txt

I percorsi relativi specificano una posizione relativa alla directory di lavoro corrente:

  • data.txt (file nella directory corrente)
  • reports/sales.txt (file in una sottodirectory)
  • ../config.txt (file nella directory padre)

La directory di lavoro corrente (CWD, current working directory) è la cartella in cui Python cerca i file quando usi percorsi relativi. Quando esegui uno script Python, la CWD è la directory da cui hai lanciato il comando, non necessariamente quella in cui si trova il file dello script.

Per esempio:

bash
# Directory structure:
/home/alice/
  └── projects/
      └── script.py
 
# Running from the projects folder:
$ cd /home/alice/projects
$ python script.py
# CWD is /home/alice/projects
 
# Running from the parent folder:
$ cd /home/alice
$ python projects/script.py
# CWD is /home/alice (not where script.py is!)

Puoi verificare la directory di lavoro corrente con:

python
import os
 
# Ottieni la directory di lavoro corrente
current_dir = os.getcwd()
print(f"Current directory: {current_dir}")

Output:

Current directory: /home/alice/projects/file_demo

La funzione os.getcwd() restituisce il percorso assoluto della directory di lavoro corrente. Questo è utile per capire dove Python cercherà i file quando usi percorsi relativi.

Comprendere la directory di lavoro corrente è importante perché determina dove Python cercherà quando usi un percorso relativo come "data.txt". Se esegui il tuo script da /home/alice/projects/ e apri "data.txt", Python cerca /home/alice/projects/data.txt.

27.1.2) Usare efficacemente i percorsi relativi

Quando lavori con i file, i percorsi relativi sono spesso più comodi dei percorsi assoluti perché rendono il codice portabile—funziona indipendentemente da dove si trova la cartella del progetto su computer diversi.

Ecco schemi comuni di percorsi relativi:

python
# File nella directory di lavoro corrente
filename = "student_grades.txt"
 
# File in una sottodirectory (cartella data all'interno della directory corrente)
filename = "data/student_grades.txt"
 
# File nella directory padre
filename = "../shared_data.txt"

Per gli esempi di questo capitolo, useremo principalmente nomi di file semplici come "data.txt". Questo significa:

  • I file di dati devono trovarsi nella stessa directory da cui esegui il comando Python
  • Se il tuo script è in /home/alice/projects/ e esegui python script.py da quella directory, Python cercherà data.txt in /home/alice/projects/

Questo approccio mantiene gli esempi chiari e focalizzati sulle operazioni sui file, piuttosto che sulla navigazione dei percorsi. Se ottieni un FileNotFoundError, usa os.getcwd() per controllare dove Python sta cercando i file.

27.1.3) Separatori di percorso tra sistemi operativi

Sistemi operativi diversi usano caratteri diversi per separare le directory nei percorsi:

  • Windows usa le barre rovesciate: data\reports\sales.txt
  • macOS e Linux usano le barre: data/reports/sales.txt

Python gestisce automaticamente questo aspetto quando usi le barre nel tuo codice—funzionano su tutti i sistemi operativi:

python
# Questo funziona su Windows, macOS e Linux
filename = "data/reports/sales.txt"

Python converte le barre nel separatore appropriato per il tuo sistema operativo.

27.2) Aprire e chiudere i file

Per lavorare con un file, dobbiamo prima aprirlo, creando una connessione tra il nostro programma e il file su disco. Quando abbiamo finito, dobbiamo chiuderlo per rilasciare le risorse di sistema e assicurarci che tutti i dati vengano salvati correttamente.

27.2.1) La funzione open()

La funzione open() crea un oggetto file (file object) che rappresenta la connessione a un file. Nella sua forma più semplice, fornisci il nome del file:

python
# Apri un file in lettura (modalità predefinita)
file = open("message.txt")

Questo apre il file message.txt nella directory corrente. La funzione open() restituisce un oggetto file, che memorizziamo nella variabile file. Questo oggetto fornisce metodi per leggere o scrivere sul file.

Tuttavia, questo approccio di base ha un problema critico: se si verifica un errore dopo l’apertura del file, il file potrebbe non essere mai chiuso. Vediamo perché chiudere i file è importante.

27.2.2) Perché è importante chiudere i file

Quando apri un file, il sistema operativo alloca risorse per mantenere quella connessione. Se non chiudi il file:

  • I dati potrebbero non essere salvati: quando scrivi su file, i dati vengono spesso bufferizzati in memoria e scritti su disco solo quando il file viene chiuso
  • Le risorse di sistema vengono sprecate: ogni file aperto consuma memoria e handle di file
  • Altri programmi potrebbero essere bloccati: alcuni sistemi impediscono ad altri programmi di accedere a un file già aperto

Per chiudere un file, chiama il suo metodo close():

python
file = open("message.txt")
# ... lavora con il file ...
file.close()  # Rilascia le risorse e assicura che i dati siano salvati

27.2.3) Il problema della chiusura manuale

Chiudere i file manualmente è soggetto a errori. Se un’eccezione si verifica tra l’apertura e la chiusura, la chiamata a close() potrebbe non essere mai eseguita:

python
file = open("data.txt")
result = process_data(file)  # Se questo solleva un'eccezione...
file.close()  # ...questo non viene mai eseguito!

Questo è un problema così comune che Python offre una soluzione migliore: l’istruzione with, di cui parleremo nella Sezione 27.4. Per ora, comprendi che aprire e chiudere i file manualmente richiede attenzione per garantire che close() venga sempre chiamato.

27.2.4) Verificare se un file è aperto

Un oggetto file ha un attributo closed che indica se il file è chiuso:

python
file = open("data.txt")
print(file.closed)  # Output: False
 
file.close()
print(file.closed)  # Output: True

Una volta che un file è chiuso, tentare di leggerlo o scriverci solleverà un errore:

python
file = open("data.txt")
file.close()
 
# This raises ValueError: I/O operation on closed file
content = file.read()

Il messaggio di errore indica chiaramente il problema: stai cercando di eseguire un’operazione di I/O (input/output) su un file che è già chiuso.

27.3) Comprendere le modalità dei file (r, w, a, testo vs binario) e la codifica

Quando apri un file, puoi specificare una modalità (mode) che determina quali operazioni sono consentite e come il file viene trattato. Comprendere le modalità è fondamentale per lavorare correttamente con i file.

27.3.1) Modalità testo vs modalità binaria

I file possono essere aperti in due modalità fondamentali:

La modalità testo (predefinita) tratta il file come contenente testo. Python automaticamente:

  • Converte i terminatori di riga in \n indipendentemente dalla piattaforma
  • Gestisce la codifica del testo (convertendo tra byte e stringhe)
  • Consente di leggere e scrivere stringhe

La modalità binaria tratta il file come byte grezzi. Python:

  • Legge e scrive oggetti bytes, non stringhe
  • Non effettua conversioni o interpretazioni
  • Si usa per immagini, audio, video e altri file non di testo

Per questo capitolo, ci concentreremo sulla modalità testo, che è quella che userai più spesso. La modalità binaria è indicata aggiungendo 'b' alla stringa della modalità (come 'rb' o 'wb'), ma non ne avremo bisogno per i file di testo.

27.3.2) Le tre modalità principali dei file

Python fornisce tre modalità principali per aprire file di testo:

Modalità lettura ('r') - Apre un file solo in lettura:

python
file = open("data.txt", "r")  # or just open("data.txt")
  • Il file deve già esistere, altrimenti Python solleva FileNotFoundError
  • Puoi leggere dal file ma non puoi scriverci
  • È la modalità predefinita se non ne specifichi una

Modalità scrittura ('w') - Apre un file in scrittura:

python
file = open("output.txt", "w")
  • Crea il file se non esiste
  • Cancella tutto il contenuto esistente se il file esiste già
  • Puoi scrivere nel file ma non puoi leggerlo
  • Usala quando vuoi creare un nuovo file o sostituire completamente uno esistente

Modalità append ('a') - Apre un file in append:

python
file = open("log.txt", "a")
  • Crea il file se non esiste
  • Preserva il contenuto esistente e aggiunge nuovo contenuto alla fine
  • Puoi scrivere nel file ma non puoi leggerlo
  • Usala quando vuoi aggiungere a un file esistente senza perdere il contenuto attuale

Ecco un confronto di come queste modalità influenzano un file esistente:

python
# Supponiamo che data.txt contenga: "Hello\nWorld\n"
 
# Modalità lettura - contenuto invariato
file = open("data.txt", "r")
file.close()
# Il file contiene ancora: "Hello\nWorld\n"
 
# Modalità scrittura - contenuto cancellato
file = open("data.txt", "w")
file.write("New content\n")
file.close()
# Il file ora contiene: "New content\n"
 
# Modalità append - contenuto preservato, nuovo contenuto aggiunto
file = open("data.txt", "a")
file.write("Added line\n")
file.close()
# Il file ora contiene: "New content\nAdded line\n"

27.3.3) Comprendere la codifica del testo

Quando lavori con file di testo, Python deve sapere come convertire tra i byte memorizzati su disco e i caratteri della stringa nel tuo programma. Questo processo di conversione si chiama codifica (encoding).

La codifica più comune è UTF-8, che può rappresentare qualsiasi carattere di qualsiasi lingua. È la codifica predefinita in Python 3 e lo standard per i moderni file di testo.

python
# Specifica esplicitamente la codifica UTF-8 (anche se di solito è la predefinita)
file = open("data.txt", "r", encoding="utf-8")

Perché la codifica è importante? Considera questo file di testo contenente un nome con un carattere accentato:

python
# Scrivere un file con caratteri speciali
file = open("names.txt", "w", encoding="utf-8")
file.write("José\n")
file.write("François\n")
file.write("Müller\n")
file.close()
 
# Rileggerlo
file = open("names.txt", "r", encoding="utf-8")
content = file.read()
file.close()
print(content)

Output:

José
François
Müller

Se provi ad aprire un file con la codifica sbagliata, potresti vedere caratteri distorti oppure ottenere un errore. Usa sempre UTF-8 per i nuovi file, a meno che tu non abbia un motivo specifico per usare una codifica diversa.

27.3.4) Variazioni aggiuntive della modalità

Python fornisce caratteri di modalità aggiuntivi che possono essere combinati con le modalità principali:

Le modalità plus consentono sia lettura sia scrittura:

  • 'r+' - Lettura e scrittura (il file deve esistere)
  • 'w+' - Scrittura e lettura (cancella il contenuto esistente)
  • 'a+' - Append e lettura (preserva il contenuto esistente)

Per i principianti, è più chiaro aprire un file una volta per la lettura e separatamente per la scrittura, invece di usare le modalità plus. In questo capitolo rimarremo sulle modalità semplici ('r', 'w', 'a').

Modalità dei file

Lettura 'r'

Scrittura 'w'

Append 'a'

Il file deve esistere
Solo lettura
Modalità predefinita

Crea se necessario
Cancella l'esistente
Solo scrittura

Crea se necessario
Preserva l'esistente
Solo scrittura

27.4) Usare with per gestire automaticamente i file

L’istruzione with fornisce un modo più pulito e sicuro per lavorare con i file. Chiude automaticamente il file quando hai finito, anche se si verifica un errore.

27.4.1) Sintassi dell’istruzione with

Ecco come usare with per aprire un file:

python
with open("data.txt", "r") as file:
    content = file.read()
    print(content)
# Il file viene chiuso automaticamente qui

La sintassi ha diverse parti:

  • with - Keyword che avvia il context manager
  • open("data.txt", "r") - Apre il file
  • as file - Crea una variabile per referenziare l’oggetto file
  • : - Inizia il blocco indentato
  • Blocco indentato - Codice che lavora con il file
  • Dopo il blocco - Il file viene chiuso automaticamente

Il vantaggio chiave: Python garantisce che il file verrà chiuso quando il blocco with termina, indipendentemente da come termina (normalmente, con un return o a causa di un’eccezione).

27.4.2) Perché with è migliore della chiusura manuale

Confronta questi due approcci:

python
# Chiusura manuale - rischiosa
file = open("data.txt", "r")
content = file.read()
result = process(content)  # Se questo solleva un'eccezione...
file.close()  # ...questo non viene eseguito
 
# Uso di with - sicuro
with open("data.txt", "r") as file:
    content = file.read()
    result = process(content)  # Anche se questo solleva un'eccezione...
# ...il file viene comunque chiuso automaticamente

L’istruzione with usa il protocollo dei context manager (context manager protocol) di Python (che esploreremo in dettaglio nel Capitolo 28). Per ora, pensalo come una garanzia: "Ripulirò questa risorsa quando hai finito, qualunque cosa accada."

27.4.3) Lavorare con più file

Puoi aprire più file in un’unica istruzione with:

python
with open("input.txt", "r") as infile, open("output.txt", "w") as outfile:
    content = infile.read()
    outfile.write(content.upper())
# Entrambi i file vengono chiusi automaticamente qui

Questo è utile quando devi leggere da un file e scrivere su un altro simultaneamente. Entrambi i file sono garantiti come chiusi correttamente, anche se si verifica un errore.

27.4.4) L’oggetto file è valido solo all’interno del blocco with

Una volta che il blocco with termina, il file è chiuso e non puoi più usare l’oggetto file:

python
with open("data.txt", "r") as file:
    content = file.read()
    print("Inside with block:", file.closed)  # Output: Inside with block: False
 
print("Outside with block:", file.closed)  # Output: Outside with block: True
 
# This raises ValueError: I/O operation on closed file
more_content = file.read()

Questo comportamento è intenzionale—impedisce che tu usi accidentalmente un file chiuso. Se ti serve il contenuto del file al di fuori del blocco with, salvalo in una variabile (come content sopra) prima che il blocco termini.

Da questo punto in avanti nel capitolo, useremo with per tutte le operazioni sui file. È l’approccio raccomandato e quello che dovresti usare nel tuo codice.

27.5) Leggere file di testo

Ora che sappiamo come aprire i file in sicurezza con with, esploriamo i diversi modi per leggere contenuti da file di testo.

27.5.1) Leggere l’intero file con read()

Il metodo read() legge l’intero contenuto del file come un’unica stringa:

python
with open("message.txt", "r") as file:
    content = file.read()
    print(content)

Se message.txt contiene:

Welcome to Python!
This is a text file.
It has multiple lines.

Output:

Welcome to Python!
This is a text file.
It has multiple lines.

Il metodo read() include tutti i caratteri di nuova riga (\n) presenti nel file. Quando stampi la stringa, Python visualizza ogni riga su una riga separata proprio grazie a questi caratteri di nuova riga.

Puoi anche leggere un numero specifico di caratteri passando un numero a read():

python
with open("message.txt", "r") as file:
    first_ten = file.read(10)  # Leggi i primi 10 caratteri
    print(f"First 10 characters: '{first_ten}'")

Output:

First 10 characters: 'Welcome to'

Leggere l’intero file è semplice e funziona bene per file piccoli. Tuttavia, per file grandi (megabyte o gigabyte), leggere tutto in una volta può consumare troppa memoria. In questi casi, leggere riga per riga è più efficiente.

27.5.2) Leggere riga per riga con readline()

Il metodo readline() legge una singola riga dal file, includendo il carattere di nuova riga alla fine:

python
with open("message.txt", "r") as file:
    line1 = file.readline()
    line2 = file.readline()
    line3 = file.readline()
    print(f"Line 1: {line1}")
    print(f"Line 2: {line2}")
    print(f"Line 3: {line3}")

Output:

Line 1: Welcome to Python!
 
Line 2: This is a text file.
 
Line 3: It has multiple lines.
 

Nota le righe vuote extra nell’output. Ogni riga letta dal file termina con \n, e print() aggiunge un’altra nuova riga. Per evitarlo, usa il metodo rstrip() per rimuovere gli spazi bianchi finali:

python
with open("message.txt", "r") as file:
    line1 = file.readline().rstrip()
    line2 = file.readline().rstrip()
    print(f"Line 1: {line1}")
    print(f"Line 2: {line2}")

Output:

Line 1: Welcome to Python!
Line 2: This is a text file.

Quando readline() raggiunge la fine del file, restituisce una stringa vuota "". Questo ti permette di rilevare quando non ci sono più righe da leggere:

python
with open("message.txt", "r") as file:
    while True:
        line = file.readline()
        if line == "":  # Fine del file
            break
        print(line.rstrip())

Tuttavia, esiste un modo più Pythonic per leggere i file riga per riga.

27.5.3) Iterare sulle righe con un ciclo for

Gli oggetti file sono iterabili (iterable), il che significa che puoi fare un ciclo direttamente su di essi con un ciclo for. Questo è il modo più comune e più Pythonic per leggere un file riga per riga:

python
with open("message.txt", "r") as file:
    for line in file:
        print(line.rstrip())

Output:

Welcome to Python!
This is a text file.
It has multiple lines.

Questo approccio è:

  • Più pulito: non c’è bisogno di readline() o di controllare stringhe vuote
  • Più efficiente: Python legge il file a blocchi, senza caricare l’intero file in memoria
  • Più Pythonic: usa l’iterazione, che è un concetto fondamentale di Python

Ogni iterazione del ciclo legge la riga successiva dal file. Quando non ci sono più righe, il ciclo termina automaticamente.

27.5.4) Leggere tutte le righe in una lista con readlines()

Il metodo readlines() legge tutte le righe dal file e le restituisce come una lista(list) di stringhe:

python
with open("message.txt", "r") as file:
    lines = file.readlines()
 
print(f"Number of lines: {len(lines)}")
for i, line in enumerate(lines, start=1):
    print(f"Line {i}: {line.rstrip()}")

Output:

Number of lines: 3
Line 1: Welcome to Python!
Line 2: This is a text file.
Line 3: It has multiple lines.

Ogni elemento della lista è una stringa contenente una riga del file, incluso il suo carattere di nuova riga. Questo è utile quando hai bisogno di:

  • Accedere alle righe per indice: lines[0], lines[1], ecc.
  • Elaborare le righe più volte
  • Conoscere il numero totale di righe prima dell’elaborazione

Tuttavia, come read(), readlines() carica l’intero file in memoria. Per file grandi, iterare con un ciclo for è più efficiente in termini di memoria.

Metodi di lettura

read

readline

iterazione con ciclo for

readlines

Intero file come stringa
Semplice ma intensivo in memoria

Una riga alla volta
Controllo manuale

Una riga per iterazione
Il più Pythonic

Tutte le righe come lista
Accesso casuale

27.6) Scrivere e aggiungere contenuto a file di testo

Scrivere sui file è importante quanto leggerli. Python offre metodi semplici per creare nuovi file o modificare quelli esistenti.

27.6.1) Scrivere su un file con write()

Per scrivere su un file, aprilo in modalità scrittura ('w') e usa il metodo write():

python
with open("output.txt", "w") as file:
    file.write("Hello, World!\n")
    file.write("This is a new file.\n")

Dopo aver eseguito questo codice, output.txt contiene:

Hello, World!
This is a new file.

Punti importanti su write():

  • Scrive una stringa nel file
  • Non aggiunge automaticamente caratteri di nuova riga—devi includere \n tu stesso
  • Restituisce il numero di caratteri scritti (anche se di solito lo ignoriamo)
  • Se il file esiste già, la modalità scrittura cancella tutto il contenuto esistente prima di scrivere

Vediamo cosa succede quando scriviamo su un file esistente:

python
# Per prima cosa, crea un file con un po' di contenuto
with open("demo.txt", "w") as file:
    file.write("Original content\n")
 
# Ora aprilo di nuovo in modalità scrittura
with open("demo.txt", "w") as file:
    file.write("New content\n")
 
# Leggi il file per vedere cosa contiene
with open("demo.txt", "r") as file:
    print(file.read())

Output:

New content

Il contenuto originale è scomparso. La modalità scrittura parte sempre da un file vuoto, che stia creando un nuovo file o sovrascrivendone uno esistente.

27.6.2) Scrivere più righe

Puoi chiamare write() più volte per scrivere più righe:

python
with open("shopping_list.txt", "w") as file:
    file.write("Apples\n")
    file.write("Bananas\n")
    file.write("Oranges\n")

27.6.3) Scrivere dati da collezioni

Un’attività comune è scrivere su un file dati provenienti da liste o altre collezioni:

python
students = ["Alice", "Bob", "Carol", "David"]
 
with open("students.txt", "w") as file:
    for student in students:
        file.write(student + "\n")

Questo crea students.txt contenente:

Alice
Bob
Carol
David

27.6.4) Aggiungere contenuto a un file (append)

Quando vuoi aggiungere contenuto alla fine di un file esistente senza cancellare ciò che c’è già, usa la modalità append ('a'):

python
# Crea un file con contenuto iniziale
with open("log.txt", "w") as file:
    file.write("Program started\n")
 
# Più tardi, aggiungi altro contenuto
with open("log.txt", "a") as file:
    file.write("Processing data\n")
    file.write("Processing complete\n")
 
# Leggi il file per vedere tutto il contenuto
with open("log.txt", "r") as file:
    print(file.read())

Output:

Program started
Processing data
Processing complete

La modalità append è perfetta per i file di log, in cui vuoi mantenere una cronologia continua degli eventi. Ogni volta che apri il file in modalità append, il nuovo contenuto viene aggiunto alla fine, preservando tutto ciò che era già presente.

27.7) Gestire gli errori comuni di I/O su file

Le operazioni sui file possono fallire per molti motivi: il file non esiste, non hai i permessi per accedervi, il disco è pieno o il file è già aperto da un altro programma. Imparare a gestire questi errori in modo elegante rende i tuoi programmi più robusti e user-friendly.

27.7.1) FileNotFoundError: quando un file non esiste

L’errore sui file più comune si verifica quando provi a leggere un file che non esiste:

python
# ATTENZIONE: questo solleverà FileNotFoundError se data.txt non esiste
with open("data.txt", "r") as file:
    content = file.read()

Se data.txt non esiste, Python solleva:

FileNotFoundError: [Errno 2] No such file or directory: 'data.txt'

Per gestirlo in modo elegante, usa un blocco try-except (come abbiamo imparato nel Capitolo 25):

python
try:
    with open("data.txt", "r") as file:
        content = file.read()
        print(content)
except FileNotFoundError:
    print("Error: The file 'data.txt' was not found.")
    print("Please check the filename and try again.")

Output (se il file non esiste):

Error: The file 'data.txt' was not found.
Please check the filename and try again.

Questo approccio impedisce al programma di andare in crash e fornisce un messaggio utile all’utente.

27.7.2) PermissionError: quando non puoi accedere a un file

A volte non hai il permesso di leggere o scrivere un file:

python
try:
    with open("/root/protected.txt", "r") as file:
        content = file.read()
except PermissionError:
    print("Error: You don't have permission to access this file.")

Gli errori di permesso possono verificarsi quando:

  • Il file appartiene a un altro utente
  • Il file si trova in una directory di sistema protetta
  • Il file è contrassegnato come di sola lettura e stai cercando di scriverci
  • Su Windows, il file è aperto in un altro programma

27.7.3) IsADirectoryError: quando provi ad aprire una directory

Se per sbaglio provi ad aprire una directory invece di un file:

python
try:
    with open("my_folder", "r") as file:
        content = file.read()
except IsADirectoryError:
    print("Error: 'my_folder' is a directory, not a file.")

Questo può succedere quando hai sia un file sia una directory con nomi simili, oppure quando dimentichi di includere il nome del file in un percorso.

27.7.4) UnicodeDecodeError: quando la codifica non corrisponde

Se provi a leggere un file con la codifica sbagliata, potresti ottenere un UnicodeDecodeError:

python
try:
    with open("data.txt", "r", encoding="utf-8") as file:
        content = file.read()
except UnicodeDecodeError:
    print("Error: The file encoding doesn't match UTF-8.")
    print("The file might use a different encoding.")

Questo errore si verifica quando il file contiene byte che non sono validi UTF-8. Se ti capita, il file potrebbe:

  • Usare una codifica diversa (come Latin-1 o Windows-1252)
  • Essere un file binario che stai cercando di leggere come testo
  • Essere corrotto

27.7.5) Gestire più tipi di errore

Puoi intercettare più tipi di errore in un singolo blocco try-except:

python
filename = input("Enter filename: ")
 
try:
    with open(filename, "r") as file:
        content = file.read()
        print(content)
except FileNotFoundError:
    print(f"Error: '{filename}' does not exist.")
except PermissionError:
    print(f"Error: You don't have permission to read '{filename}'.")
except IsADirectoryError:
    print(f"Error: '{filename}' is a directory, not a file.")
except UnicodeDecodeError:
    print(f"Error: '{filename}' contains invalid text encoding.")

Questo fornisce messaggi di errore specifici e utili per ogni tipo di problema. L’utente sa esattamente cosa è andato storto e può intraprendere l’azione appropriata.

27.7.6) Usare un gestore di eccezioni generico (catch-all)

A volte vuoi intercettare qualsiasi errore imprevisto legato ai file oltre ai tipi specifici che abbiamo coperto. Puoi usare un gestore generale Exception come catch-all dopo i gestori specifici:

python
filename = input("Enter filename: ")
 
try:
    with open(filename, "r") as file:
        content = file.read()
        print(content)
except FileNotFoundError:
    print(f"Error: '{filename}' not found.")
except PermissionError:
    print(f"Error: No permission to read '{filename}'.")
except IsADirectoryError:
    print(f"Error: '{filename}' is a directory.")
except UnicodeDecodeError:
    print(f"Error: '{filename}' has invalid encoding.")
except Exception as e:
    print(f"Unexpected error reading file: {e}")

Questo assicura che il programma gestisca anche errori che non avevi previsto. La variabile e contiene l’oggetto eccezione, che include un messaggio di errore descrittivo. Stamparlo fornisce all’utente dettagli tecnici su cosa è andato storto.


Lavorare con i file è una competenza fondamentale nella programmazione. Hai imparato come:

  • Comprendere i percorsi dei file e la directory di lavoro corrente
  • Aprire e chiudere i file correttamente
  • Usare diverse modalità dei file per leggere, scrivere e aggiungere contenuto
  • Gestire automaticamente i file con l’istruzione with
  • Leggere i file usando vari metodi (read(), readline(), iterazione, readlines())
  • Scrivere e aggiungere contenuto ai file
  • Gestire in modo elegante gli errori comuni di I/O su file

Queste competenze ti permettono di creare programmi che persistono dati tra esecuzioni, elaborare file di testo, generare report e molto altro. Nel prossimo capitolo esploreremo in profondità i context manager, comprendendo il meccanismo che fa funzionare l’istruzione with e come creare i tuoi context manager per gestire risorse oltre ai file.

© 2025. Primesoft Co., Ltd.
support@primesoft.ai