Spesso è necessario, per il progettista programmatore Python, avere il totale controllo di come le eccezioni debbano essere gestite, quindi spesso è necessario che il programmatore possa inserire del codice a seguito del raise di un'eccezione, e soprattutto ci sono casi nei quali è necessario che il programma non si arresti, ma segnali l'errore in qualche modo, provi a gestirlo in qualche altro modo, ma continui di fatto la sua esecuzione al verificarsi dell'eccezione. In tal caso è possibile utilizzare il costrutto Python Try_Except, che serve ad incapsulare il codice che potenzialmente potrebbe sollevare le eccezioni. Se l'istruzione presente nel blocco Try non solleva eccezioni, allora il blocco può essere eseguito e si continua l'esecuzione normalmente. Altrimenti, se un'istruzione del blocco Try solleva un'eccezione, allora il codice non viene eseguito, ma viene eseguito il codice del blocco Except, che con ogni probabilità , se è scritto bene, serve appunto per gestire il verificarsi di quell'eccezione e permettere il continuo del programma. Mettiamoci in un caso: scriviamo una stringa banalissima. Definita la stringa, andiamo a definire una funzione estrai, che da una stringa s estrae il carattere in posizione i. Banalmente, andrebbe a restituire s[i]... Quindi, nel caso io invochi estrai sulla stringa x in posizione 2, nessun problema, otterrò una a perché c posizione 0, i posizione 1, a posizione 2. Viceversa, se invocassi estrai sulla stringa x in posizione 4, la nostra stringa ha quattro caratteri, quindi l'ultimo carattere, essendo Python zero-based, si troverà in posizione 3. Quindi dovremmo avere un errore di indice non valido, e infatti errore sull'indice. Attenzione che il tuo indice sulla stringa è out of range, è fuori dal range degli indici ammissibili, che per il mio ciao di quattro caratteri sarebbe stato da 0 a 3. In questo caso è possibile gestire l'eccezione, fare in modo da definire un blocco di codice che si può comportare in un certo modo se un'eccezione è stata sollevata, in quanto appunto non possiamo perdere il controllo del nostro codice e molto spesso è estremamente desiderabile che il programma non si blocchi, ma continui la sua esecuzione. Ecco qui il costrutto Try_Except. In Try andiamo a inserire il codice che potenzialmente potrebbe raise, innalzare un'eccezione. Try: estrai x di 4. Adesso, che succede? except Index IndexError è solo una label che do io per etichettare il blocco di istruzioni che si occupano della gestione dell'eccezione. I due punti sono essenziali. Non faccio nulla, semplicemente notifico che c'è stata un'eccezione e che il programma, preso atto, notificato all'utente che è avvenuta un'eccezione, il programma continuerà . Allora, forse ho... Ecco qui. Try ha provato ad estrarre il quarto elemento da x e non ci è riuscito, e allora ha attivato il blocco di gestione dell'eccezione, e quindi abbiamo avuto la stampa sia di eccezione, sia del blocco continua. Gli script stessi possono generare eccezioni: è possibile, per l'utente programmatore, inviare un'eccezione tramite un'istruzione che si chiama raise: le eccezioni sollevate dall'utente, ovviamente, sono sempre sincrone con il flusso di esecuzione, e sono catturate però nello stesso modo di quelle generate dal sistema. Per esempio, se noi volessimo forzare la generazione di un'eccezione di tipo IndexError, dovremmo, nel blocco Try, forzare questa eccezione. Solleva, raise IndexError: stai sollevando un'eccezione di IndexError manualmente, e la stiamo anche gestendo. Nel caso in cui fosse sollevata un'eccezione di IndexError, e lo è perché l'abbiamo forzata, questo è il blocco di istruzioni che la gestisce. Nel nostro caso, sempre un banale print: ho sollevato l'eccezione. Inoltre il costrutto Try può includere blocchi di terminazione finally. La combinazione Try e finally specifica le azioni di terminazione che vengono eseguite sempre in uscita, indipendentemente dal fatto che si verifichi un'eccezione nel blocco Try o meno. Se il blocco Try termina senza eccezioni, il blocco finally verrà eseguito, e il programma riprenderà il suo flusso normale di esecuzione dopo il blocco Try. Per esempio i: forziamo i ad essere un intero. Utilizziamo la funzione input: input che dà un messaggio all'utente e riceve un carattere, riceve quello che l'utente immette da tastiera. Inserisci l'indice del carattere che vuoi estrarre. Uso i doppi apici, perfetto. Allora, cosa faccio adesso? Try, quindi ho il mio codice di sentinella, estrai (x,i): voglio estrarre il carattere che l'utente ha appena messo, di indice appena messo dall'utente, dalla mia solita stringa x. Cosa ho in except? Ho una stampa di è stata sollevata...: va da sé che se l'utente inserisce 2, 2 è ammissibile, non entriamo in questo caso. Sollevata una eccezione e poi abbiamo un altro ramo, il ramo finally. Questo ramo finally viene eseguito anche se non è stata sollevata alcuna eccezione. Anche se non è stata sollevata un'eccezione. Ovviamente, usando opportunamente. Quindi eseguo questo blocco. Mettiamo che io inserisca 2, o anche 0: tutto a posto, non entriamo proprio nel blocco except, non è stata sollevata nessuna eccezione, ma entriamo nel blocco finally e infatti abbiamo il suo print: eseguito anche se non è stata sollevata un'eccezione. Ancora lo rieseguo, inserisco 57 come indice e quindi (p è un errore mio) è stata sollevata un'eccezione, scritta un po' meglio, ma comunque ci fa capire che siamo entrati nel blocco except e comunque entriamo anche nel blocco finally di chiusura.