2.25. Gestione degli errori¶
La maggior parte dei problemi a runtime in Python si manifesta come eccezioni – un modo strutturato e con un nome per segnalare che qualcosa è andato storto. ValueError, TypeError, KeyError, OSError, MemoryError sono tutti esempi; ciascuna è una classe, e sollevare (raising) una di esse interrompe la chiamata corrente e cerca un gestore nel codice circostante.
2.25.1. try / except¶
Racchiudi un blocco di codice in try per intercettare qualsiasi eccezione esso sollevi:
try:
n = int(input_text)
except ValueError:
n = 0
Se la conversione int(...) fallisce, il controllo passa al blocco except invece di propagare ulteriormente l’errore. Se input_text era una stringa intera valida, il blocco except viene saltato.
Un singolo try può avere diversi blocchi except, ciascuno dei quali intercetta un diverso tipo di errore:
try:
value = data[key]
except KeyError:
value = None
except TypeError:
value = -1
Python confronta nell’ordine; il primo la cui classe di eccezione corrisponde gestisce il problema. Intercettare Exception (la classe base per quasi tutto) gestisce qualsiasi errore; riserva questa pratica al livello più esterno di un programma, dove l’alternativa è un crash.
Avvertimento
Un except: nudo (senza classe dopo la parola chiave) intercetta anche KeyboardInterrupt – l’eccezione che l’IDE invia quando premi il suo pulsante stop per interrompere uno script in esecuzione. Un ciclo racchiuso in un except: pass nudo inghiottirà l’interruzione e continuerà a girare, senza lasciare alcun modo di fermare lo script se non spegnendo e riaccendendo.
Preferisci except Exception: rispetto a except: nudo quando hai davvero bisogno di intercettare in modo ampio. KeyboardInterrupt eredita da BaseException, non da Exception, quindi except Exception: lascia funzionante il pulsante stop.
2.25.1.1. Esaminare l’eccezione¶
Per leggere il messaggio associato a un’eccezione, assegnale un nome con as:
try:
f = open("data.txt")
except OSError as e:
print("could not open file:", e)
La variabile associata da as è valida solo all’interno del blocco except.
2.25.2. else e finally¶
Un blocco try ha due elementi opzionali aggiuntivi.
else viene eseguito solo quando il try è terminato senza sollevare eccezioni:
try:
value = compute()
except ValueError:
print("bad input")
else:
print("got", value)
Mettere «cosa fare quando ha funzionato» in else mantiene stretto il blocco try – solo la riga che potrebbe fallire appartiene a try.
finally viene eseguito alla fine in ogni caso – che il try abbia avuto successo, abbia sollevato un’eccezione che è stata gestita, oppure abbia sollevato un’eccezione che sta per propagarsi:
try:
do_work()
finally:
cleanup()
finally viene sempre eseguito. else viene eseguito solo sul percorso senza eccezioni.¶
Per la maggior parte degli schemi di acquisizione/rilascio, preferisci un context manager rispetto a una coppia try / finally – la risorsa stessa gestisce la propria pulizia.
2.25.3. Eccezioni built-in comuni¶
Un breve elenco delle eccezioni in cui ti imbatterai spesso:
ValueError– tipo corretto, valore errato (bytes([300])– 300 è del tipo corretto, ma è al di fuori dell’intervallo di byte valido 0..255).TypeError– tipo del tutto sbagliato (len(42)).IndexError– indice oltre la fine di una sequenza.AttributeError– accesso a un attributo che non esiste ("abc".foo).OSError– un errore del filesystem o di I/O.MemoryError– heap esaurito. Su un runtime con memoria limitata, questo può accadere durante il normale funzionamento – non solo in casi patologici.