Video Corso Base di Python 3

13: A prova di crash - Come gestire gli Errori

Menu della Serie






Ciao a tutti brava gente, benvenuti a questa tredicesima puntata della serie dedicata alle basi di Python 3.6!

Come il titolo vi avrà suggerito, questa è una lezione dedicata alla gestione intelligente e produttiva degli errori che si possono verificare durante l'esecuzione dei nostri programmi.
Parlando di errori mi riferisco in realtà a quelle eccezioni che quando si manifestano, comportano il crash del programma e l'interruzione istantanea dell'esecuzione del codice.




Un'eccezione tipica è quella che si manifesta quanto proviamo ad effettuare una divisione per zero, che restituisce appunto un ZeroDivisionError:

>>> 3/0
ZeroDivisionError: division by zero

Un'altro messaggio di errore ci viene presentato se proviamo ad utilizzare una variabile non dichiarata...

>>> z * 5
NameError: name 'z' is not defined

Questi messaggi di errore sono piuttosto comodi per noi sviluppatori, prima di tutto per risolvere i vari bug che inevitabilmente si presentano.
Inoltre il livello di dettaglio che ci viene fornito da Python è davvero impressionante se paragonato a tanti altri linguaggi di programmazione, e questo è uno dei tantissimi vantaggi del linguaggio più bello del mondo.
Anche molti moduli vengono ideati e pubblicati con un certo livello di dettaglio nel caso si manifesti un'eccezione.

È importante gestire questi errori perché oltre a causare il crash del programma sono esteticamente poco gradevoli e incomprensibili sopratutto a chi sta utilizzando un programma scritto da qualcun'altro.

Per gestire queste eccezioni utilizziamo due istruzioni utilissime: try ed except, che significano "prova" e "eccetto" o "a accezzione di".
Volendo potete immaginarli un pó come degli if / else ideati per la gestione delle eccezioni.
Il codice inserito nel try verrà eseguito qualora tutto andasse come pianificato, senza errori,mentre il codice inserito nell'EXCEPT verrà eseguito solamente qualora si verifichi l'errore ad esso associato.

Apriamo l'editor testuale e facciamo un esempio in cui gestiremo l'eccezione "ZeroDivisionError".

def divisore(a,b):
try:
risultato = a / b
print('Il Risultato della divisione è: ' + str(risultato))
except ZeroDivisionError:
print('Hai effettuato una divisione per Zero... causando così un errore!')


Uno dei momenti in cui le istruzioni try ed except risultano quasi indispensabili è proprio quando si richiede all'utente di introdurre dei valori.

Facciamo un altro esempio, stavolta con una moltiplicazione:

def moltiplicatore():
a = int(input('Inserisci il valore di a: '))
b = int(input('Inserisci il valore di b: '))
risultato = a * b
print(risultato)

Proviamo ad eseguire il codice... e a forzarlo introducendo dei caratteri non numerici all'interno delle variabili a e b:

>>> moltiplicatore()
Inserisci il valore di a: asd

ValueError: invalid literal for int() with base 10: 'asd'

Abbiamo ottenuto un ValueError, ovvero un errore di valore, perché la funzione int() non è in grado, ovviamente, di convertire la stringa "asd" in un numero intero.

Andiamo a modificare il programma in modo da poter gestire questa eventualità...

def moltiplicatore():
try:
a = int(input('Inserisci il valore di a: '))
b = int(input('Inserisci il valore di b: '))
risultato = a * b
print(risultato)
except ValueError:
print('Hey amico! solo caratteri numerici, grazie!')

E rieseguiamo il tutto...

>>> moltiplicatore()
Inserisci il valore di a: asd
Hey amico! solo caratteri numerici, grazie!

Quindi qualora siata in fase di progettazione di un programma, e notate che ci sono delle eventualità in cui, per quanto il programma sia ben strutturato, si arriva comunque a dei crash, come appunto in questi casi presentati,
semplicemente copiate il nome dell'errore e usatelo assieme ad except per poter gestire questa eccezione.
Così facendo il programma avrà tutto un altro livello di professionalità!<7p>


Un'altra istruzione di cui è bene parlare è l'istruzione finally, traducibile in questo caso come "alla fine" o "infine".

Come il nome stesso suggerisce, il codice definito nel blocco di finally verrà eseguito alla fine del programma, qualsiasi cosa succeda, ovvero che si manifesti un errore oppure no.
Andiamo a modificare la nostra funzione moltiplicatore():

def moltiplicatore():
try:
a = int(input('Inserisci il valore di a: '))
b = int(input('Inserisci il valore di b: '))
risultato = a * b
print(risultato)
except ValueError:
print('Hey amico! solo caratteri numerici, grazie!')
finally:
print('Grazie per aver utilizzato questa applicazione!')

e proviamo ad eseguirla facendo apparire sia l'eccezione che no:
Come vediamo, la stringa 'Grazie per aver utilizzato questa applicazione!' viene mandata in output qualsiasi cosa succeda!




Ricapitolando:
-Per quanto utili in fase di sviluppo, gli errori sono scomodi e causano il crash del programma;
-Possiamo gestire questi errori mediante l'utilizzo delle istruzioni TRY e EXCEPT;
-Il codice nel blocco di EXCEPT viene eseguito solo in caso un errore si manifesti;
-Mediante l'ustruzione FINALLY possiamo delineare del codice che verrà eseguito qualsiasi cosa succeda.