In Python, tutte le eccezioni derivano dalla classe BaseException. Ciò significa che ogni eccezione in Python è un'istanza di BaseException o di una delle sue sottoclassi.
La classe BaseException è la classe di livello più alto nella gerarchia delle eccezioni. Fornisce alcuni metodi comuni che tutte le eccezioni possono utilizzare, come __str__ e __repr__. Tuttavia, non dovresti usare direttamente BaseException nel tuo codice, poiché è troppo generica e può catturare qualsiasi tipo di eccezione. Invece, dovresti utilizzare classi di eccezione più specifiche che sono sottoclassi di BaseException. Python fornisce numerose classi di eccezioni integrate che puoi utilizzare, e puoi anche creare le tue classi di eccezioni personalizzate:
The hierarchy of built-in exception classes in Python (from the official Python docs).
Ciò significa che FileNotFoundError è una sottoclasse di OSError, che è una sottoclasse della classe Exception, che a sua volta eredita da BaseException.
Rispettare la gerarchia delle eccezioni
Quando si utilizzano più istruzioni except, è importante rispettare la gerarchia delle eccezioni in Python. Ciò significa che se si cattura una classe di eccezione base, come Exception, si dovrebbero catturare le eccezioni più specifiche prima di essa. Se scrivi un'istruzione except per una classe più specifica dopo la classe base, quel blocco non verrà eseguito:
try:
# del codice che potrebbe sollevare un'eccezione
except ValueError:
# gestisce il ValueError
except Exception:
# gestisce qualsiasi altra eccezione
In questo esempio, l'eccezione ValueError viene catturata per prima. Se il codice genera qualsiasi altra eccezione che deriva da Exception, verrà eseguito il codice nel secondo blocco except. Tuttavia, non è consigliabile catturare direttamente Exception, poiché è troppo generica e può catturare qualsiasi tipo di eccezione. È meglio catturare eccezioni più specifiche quando possibile:
Se il codice nel blocco try solleva un TypeError o un ValueError, verrà eseguito il corrispondente blocco except. Se il codice solleva qualsiasi altra eccezione che deriva da Exception, verrà eseguito il codice nel terzo blocco except.
Se posizioniamo l'eccezione base come primo blocco except, impedirà agli altri di essere eseguiti:
try:
# del codice che potrebbe sollevare un'eccezione
except Exception as e: # Questo catturerà tutti gli errori
print(f'An error occurred: {e}')
except ValueError: # Questo non verrà mai eseguito
print('A ValueError occurred')
except TypeError: # Questo non verrà mai eseguito
print('A TypeError occurred')
In questo esempio, il blocco try può sollevare qualsiasi tipo di eccezione. Tuttavia, la prima istruzione except cattura la classe base Exception, quindi catturerà qualsiasi eccezione sollevata. Verrà stampato il messaggio di errore e il resto delle istruzioni except non verranno eseguite.
Sfida: Analizza il file
Stai lavorando come ingegnere del software in una startup che gestisce grandi quantità di dati. Recentemente, il team ha deciso di utilizzare file JSON per memorizzare e elaborare i dati. Questi dati sono vitali per il funzionamento della tua startup, e il tuo compito è scrivere un programma Python che legga e analizzi questi file JSON.
Tuttavia, a causa della grande quantità di dati e delle molte persone che ci lavorano, si verificano spesso alcuni errori:
A volte il file di dati non esiste.
A volte il file di dati è vuoto.
A volte il file di dati contiene dati che non sono JSON valido.
Devi assicurarti che il tuo programma Python possa gestire queste eccezioni senza andare in crash e fornire messaggi di errore significativi in modo che il team dei dati possa identificare e risolvere rapidamente il problema.
Il tuo programma dovrebbe prendere in input una stringa che rappresenta il nome del file e gestire i seguenti casi:
Se il file non esiste, dovrebbe sollevare un FileNotFoundError e stampare un appropriato messaggio di errore.
Se il file è vuoto, dovrebbe sollevare un ValueError e stampare un appropriato messaggio di errore.
Se il contenuto del file non è JSON valido, dovrebbe sollevare un json.JSONDecodeError (che è una sottoclasse di ValueError) e stampare un appropriato messaggio di errore. Quando sollevi questa eccezione, dovresti fornire gli attributi doc e pos come parametri.
💡
except json.JSONDecodeError as e:
Ciascuna di queste eccezioni dovrebbe essere gestita indipendentemente dalle altre, e il tuo programma dovrebbe fornire un messaggio di errore specifico per ogni caso.
Ingresso
Uscita
nonexistent_file.json
FileNotFoundError: File 'nonexistent_file.json' does not exist.
empty_file.json
ValueError: File 'empty_file.json' is empty.
invalid_json.json
JSONDecodeError: Content of file 'invalid_json.json' is not valid JSON.: line 1 column 1 (char 0)
success.json
File 'success.json' has been successfully parsed as valid JSON.