Eccezioni in Python
In questa pagina 6
Che cosa sono
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).
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
| Eccezione | Causa tipica |
|---|---|
NameError |
nome non definito (refuso, variabile non ancora assegnata) |
TypeError |
operazione su un tipo sbagliato ("a" + 1, None + 1, numero di argomenti errato) |
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 (lista.push(1)) |
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
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")- I rami
exceptvengono provati in ordine: il primo compatibile vince. - Nel
trymettere solo le istruzioni che possono sollevare l'eccezione attesa. 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
Una funzione che riceve argomenti non validi non deve stampare un messaggio e proseguire: deve segnalare l'errore al chiamante.
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.