6. Eccezioni
Ora esamineremo le eccezioni.
![]() |
Il primo script illustra la necessità di gestire le eccezioni.
Provociamo intenzionalmente un errore per vedere le informazioni prodotte dall'interprete. L'output è il seguente:
La riga 4 ci fornisce:
- il tipo di eccezione: ZeroDivisionError;
- il messaggio di errore associato: divisione intera o modulo per zero. È in inglese. È qualcosa che potresti voler cambiare.
La regola fondamentale nella programmazione è che dobbiamo fare tutto il possibile per evitare crash "incontrollati" come quello sopra. Anche in caso di errore, il programma deve terminare correttamente fornendo informazioni sull'errore verificatosi.
La sintassi per la gestione delle eccezioni è la seguente:
try:
actions susceptibles de lancer une exception
except [classe d'exception, ...]:
actions de gestion de l'exception
finally:
actions toujours exécutées qu'il y ait exception ou non
Nel blocco try, l'esecuzione delle azioni si interrompe non appena si verifica un'eccezione. In questo caso, l'esecuzione prosegue con le azioni nella clausola except.
Il
except [MyException, ...]:
intercetta le eccezioni di tipo MyException o dei tipi derivati. Quando si verifica un'eccezione in un blocco try, l'interprete esamina le clausole except associate al blocco try nell'ordine in cui sono state scritte. Si ferma alla prima clausola except in grado di gestire l'eccezione verificatasi. Se non ne trova nessuna, l'eccezione viene propagata al metodo chiamante. Se quel metodo ha un blocco try/except, l'eccezione viene gestita nuovamente; altrimenti, continua a propagarsi lungo la catena dei metodi chiamati. Alla fine, raggiunge l'interprete Python. L'interprete quindi termina il programma in esecuzione e visualizza un messaggio di errore del tipo mostrato nell'esempio precedente. La regola è quindi che il programma principale deve intercettare tutte le eccezioni che potrebbero propagarsi dai metodi chiamati.
Un'eccezione contiene informazioni sull'errore verificatosi. Queste informazioni possono essere recuperate utilizzando la seguente sintassi:
except MyException as informations:
information è una tupla che contiene le informazioni relative all'eccezione.
La sintassi
except MyException, erreur:
assegna il messaggio di errore associato all'eccezione alla variabile error.
Per generare un'eccezione, utilizzare la sintassi
raise MyException(param1, param2, ...)
dove MyException è solitamente una classe derivata dalla classe Exception. I parametri passati al costruttore della classe saranno disponibili per la clausola except delle strutture di gestione delle eccezioni.
Questi concetti sono illustrati dal seguente script.
Il seguente script gestisce esplicitamente gli errori:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | |
Note:
- righe 6–9: gestione della divisione per zero;
- riga 8: intercettiamo l'eccezione esatta che si verifica;
- riga 11: a causa dell'eccezione verificatasi, x non ha ricevuto un valore e quindi non è cambiata;
- righe 15-19: facciamo la stessa cosa ma intercettiamo un'eccezione di livello superiore di tipo Exception. Poiché l'eccezione ZeroDivisionError deriva dalla classe Exception, la clausola except la intercetterà;
- righe 23–33: includiamo più clausole except per gestire più tipi di eccezioni. Verrà eseguita solo una clausola except, oppure nessuna se l'eccezione non corrisponde a nessuna clausola except;
- righe 51–55: la clausola except può non avere argomenti. In questo caso, intercetta tutte le eccezioni;
- righe 59–62: introduciamo l'eccezione ValueError;
- righe 66–69: recuperiamo le informazioni contenute nell'eccezione;
- righe 73–76: spiegano come generare un'eccezione;
- righe 79–84: illustrano l'uso di una classe di eccezione personalizzata, MyError;
- righe 79–80: la classe MyError eredita semplicemente dalla classe base Exception. Non aggiunge nulla alla sua classe base. Ma ora può essere esplicitamente nominata nelle clausole except;
- righe 97–107: dimostrano che in Python è possibile generare qualsiasi tipo di oggetto, non solo oggetti derivati dalla classe Exception;
- Righe 109–127: dimostrano l'uso della clausola finally.
L'output sullo schermo è il seguente:
0 : integer division or modulo by zero
x=2
1 : integer division or modulo by zero
2 : (Exception) integer division or modulo by zero
3 : (ZeroDivisionError) integer division or modulo by zero
4 : il y a eu un probleme
5 : invalid literal for int() with base 10: 'x'
6 : invalid literal for int() with base 10: 'x'
7 : ('param1', 'param2', 'param3')
8 : ('info1', 'info2', 'info3')
9 : mon msg d'erreur
10 : pb...
11 : finally x=1
12 : exception
12 : finally x=None
Questo nuovo script illustra come le eccezioni vengono propagate lungo la catena dei metodi di chiamata:
Note:
- Righe 27–30: nella chiamata main --> f1 --> f2 --> f3 (riga 28), l'eccezione MyError generata da f3 si propagherà fino a main. Verrà quindi gestita dalla clausola except alla riga 29;
- righe 55–58: nella chiamata main → f4 → f5 → f6 (riga 56), l'eccezione MyError generata da f6 si propagherà fino a main. Verrà quindi gestita dalla clausola except alla riga 29. Questa volta, mentre si propaga lungo la catena dei metodi di chiamata, l'eccezione MyError viene arricchita con le informazioni aggiunte da ciascun metodo lungo il percorso.
L'output sullo schermo è il seguente:
