Eccezioni in Python
In questa pagina 6
In questa pagina 6
Che cosa sono
Definizione (eccezione). Un'eccezione è un oggetto che segnala un errore a tempo di esecuzione. Quando viene sollevata, l'esecuzione normale si interrompe e l'eccezione risale lo stack delle chiamate finché qualcuno la gestisce; se nessuno la gestisce il programma termina stampando il traceback (sequenza delle chiamate, dalla più esterna alla riga dell'errore, e in fondo tipo e messaggio).
Esempio. int("abc") solleva ValueError e [1, 2][5] solleva IndexError.
Traceback (most recent call last):
File "prog.py", line 5, in <module>
print(media([]))
File "prog.py", line 2, in media
return sum(v) / len(v)
ZeroDivisionError: division by zeroSi legge dal fondo: tipo dell'eccezione, poi la riga che l'ha provocata, poi chi l'ha chiamata.
Eccezioni comuni
Definizione (eccezioni comuni)
Eccezione Causa tipica NameErrornome non definito (refuso, variabile non ancora assegnata) TypeErroroperazione su un tipo sbagliato ( "a" + 1,None + 1, numero di argomenti errato)ValueErrortipo giusto, valore inammissibile ( int("abc"))IndexErrorindice fuori dalla sequenza KeyErrorchiave assente in un dizionario ZeroDivisionErrordivisione o modulo per zero AttributeErrormetodo o attributo inesistente ( lista.push(1))FileNotFoundErrorfile da leggere inesistente RecursionErrorricorsione troppo profonda (vedi RicorsioneFunzioni che chiamano se stesse: caso base e passo ricorsivo, stack delle chiamate, esempi su numeri, stringhe e liste, ricorsione multipla e suo costo, divide et impera, confronto con l'iterazione.Ricorsione →)
Esempio. {"a": 1}["b"] solleva KeyError, "a" + 1 solleva TypeError e 1 / 0 solleva ZeroDivisionError.
try / except
try:
n = int(input("Numero: "))
print(100 / n)
except ValueError:
print("non è un intero")
except ZeroDivisionError:
print("zero non ammesso")Forme complete:
try:
f = open(nome, encoding="utf-8")
except FileNotFoundError as e: # "as e": l'oggetto eccezione
print("Impossibile aprire:", e)
except (ValueError, TypeError): # più tipi nello stesso ramo
...
else:
# eseguito solo se nel try non c'è stata eccezione
dati = f.read()
f.close()
finally:
# eseguito sempre (con o senza eccezione): rilascio di risorse
print("fine")Proprietà (ordine dei rami except)
- I rami
exceptvengono provati in ordine: il primo compatibile vince.- Nel
trymettere solo le istruzioni che possono sollevare l'eccezione attesa.
Esempio. Con except ValueError prima di except ZeroDivisionError, l'input abc entra nel primo ramo e l'input 0 nel secondo.
except Exception:cattura quasi tutto: va usato solo con cognizione (es. per registrare l'errore e rilanciarlo). Unexcept:nudo nasconde anche i bug.
Sollevare eccezioni: raise
Definizione (raise). Una funzione che riceve argomenti non validi non deve stampare un messaggio e proseguire: deve segnalare l'errore al chiamante.
Esempio. raise ValueError("n negativo") interrompe la funzione e il chiamante può intercettare l'errore con except ValueError.
def media(valori):
if len(valori) == 0:
raise ValueError("media di una lista vuota")
return sum(valori) / len(valori)Il chiamante decide se gestirla. raise da solo dentro un except rilancia l'eccezione corrente.
Eccezioni o controlli preventivi
Due stili:
# controllo prima (LBYL: look before you leap)
if chiave in d:
v = d[chiave]
# prova e gestisci (EAFP: easier to ask forgiveness than permission)
try:
v = d[chiave]
except KeyError:
v = 0In Python entrambi sono accettati; EAFP è naturale quando il caso d'errore è raro o il controllo preventivo è difficile (input dell'utente, file). In C non ci sono eccezioni: gli errori si segnalano con valori di ritorno (vedi Input e output in Cprintf con larghezza e precisione, scanf con indirizzi e valore di ritorno, lettura di righe con fgets, file con FILE*, fopen, fclose, fprintf, fscanf, controllo degli errori e della fine del file.Input e output in C →).
Errori tipici
except:vuoto oexcept Exception: pass, che nasconde gli errori veri.- Blocco
trytroppo grande: si catturano eccezioni di righe che non c'entrano. - Usare le eccezioni al posto di un normale
ifper casi frequenti e prevedibili.
Versione ripasso
Che cosa sono
Un'eccezione è un oggetto che segnala un errore a tempo di esecuzione. Se non gestita, interrompe l'esecuzione stampando il traceback (dalla chiamata più esterna alla riga dell'errore).
Eccezioni comuni
| Eccezione | Causa tipica |
|---|---|
NameError |
nome non definito |
TypeError |
operazione su un tipo sbagliato |
ValueError |
tipo giusto, valore inammissibile (int("abc")) |
IndexError |
indice fuori dalla sequenza |
KeyError |
chiave assente in un dizionario |
ZeroDivisionError |
divisione o modulo per zero |
AttributeError |
metodo o attributo inesistente |
FileNotFoundError |
file da leggere inesistente |
RecursionError |
ricorsione troppo profonda (vedi RicorsioneFunzioni che chiamano se stesse: caso base e passo ricorsivo, stack delle chiamate, esempi su numeri, stringhe e liste, ricorsione multipla e suo costo, divide et impera, confronto con l'iterazione.Ricorsione →) |
try / except / else / finally
try:
f = open(nome, encoding="utf-8")
except FileNotFoundError as e:
print("Impossibile aprire:", e)
except (ValueError, TypeError):
...
else:
# eseguito solo se nel try non c'è stata eccezione
dati = f.read()
f.close()
finally:
# eseguito sempre (con o senza eccezione)
print("fine")- I rami
exceptsi provano in ordine: il primo compatibile vince. except Exception:cattura quasi tutto; unexcept:nudo nasconde anche i bug.
Sollevare eccezioni: raise
def media(valori):
if len(valori) == 0:
raise ValueError("media di una lista vuota")
return sum(valori) / len(valori)raise da solo dentro un except rilancia l'eccezione corrente.
LBYL vs EAFP
- LBYL (look before you leap): controllo preventivo (
if chiave in d:). - EAFP (easier to ask forgiveness than permission): prova e gestisci (
try... except KeyError:).
Errori tipici
except:vuoto oexcept Exception: passche nasconde gli errori veri.- Blocco
trytroppo grande. - Usare le eccezioni al posto di un normale
ifper casi frequenti.
Esercizi su questo argomento
Teoria collegata
- Java servlet e Apache Tomcat - ciclo di vita, richieste e sessioni
- JavaScript - linguaggio, DOM ed eventi
- Classi ed ereditarietà in Python
- Debugging e testing
- Eseguire un programma Python
- File di record e controllo degli errori riga per riga
- File di testo in Python
- Input e output da console
- Input e output in C
- Tipi numerici ed espressioni
- C++ - eccezioni e gestione delle risorse (RAII)