Gérer les exceptions
Qu’est-ce donc ?
Une exception est levée quand une erreur est commise
[1]:
nexistepas
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[1], line 1
----> 1 nexistepas
NameError: name 'nexistepas' is not defined
[2]:
2 / 0
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
Cell In[2], line 1
----> 1 2 / 0
ZeroDivisionError: division by zero
[3]:
'un' + 2
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[3], line 1
----> 1 'un' + 2
TypeError: can only concatenate str (not "int") to str
[4]:
'bonjour'[9]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
Cell In[4], line 1
----> 1 'bonjour'[9]
IndexError: string index out of range
[5]:
{'un': 1}['deux']
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
Cell In[5], line 1
----> 1 {'un': 1}['deux']
KeyError: 'deux'
Le Traceback permet de suivre l’imbrication des appels au moment de l’erreur
[6]:
def f0(x):
return x / 0
def f1(x):
return f0(x) / 1
def f2(x):
return f1(x) / 2
def f3(x):
return f2(x) / 3
f3(1)
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
Cell In[6], line 13
10 def f3(x):
11 return f2(x) / 3
---> 13 f3(1)
Cell In[6], line 11, in f3(x)
10 def f3(x):
---> 11 return f2(x) / 3
Cell In[6], line 8, in f2(x)
7 def f2(x):
----> 8 return f1(x) / 2
Cell In[6], line 5, in f1(x)
4 def f1(x):
----> 5 return f0(x) / 1
Cell In[6], line 2, in f0(x)
1 def f0(x):
----> 2 return x / 0
ZeroDivisionError: division by zero
Il est possible d’émettre soit même une exception pour signaler une erreur.
[7]:
def fonction_qui_n_aime_pas_toto(valeur):
""" affiche valeur
Je n'aime pas Toto, donc 'toto' est une valeur interdite !
"""
if valeur == 'toto':
raise ValueError("T'es pas beau, toto !") # pensez à mettre un message utile...
print(valeur)
[8]:
fonction_qui_n_aime_pas_toto('tata')
tata
[9]:
fonction_qui_n_aime_pas_toto('toto')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[9], line 1
----> 1 fonction_qui_n_aime_pas_toto('toto')
Cell In[7], line 6, in fonction_qui_n_aime_pas_toto(valeur)
2 """ affiche valeur
3 Je n'aime pas Toto, donc 'toto' est une valeur interdite !
4 """
5 if valeur == 'toto':
----> 6 raise ValueError("T'es pas beau, toto !") # pensez à mettre un message utile...
7 print(valeur)
ValueError: T'es pas beau, toto !
De nombreuses exceptions sont définies de base
https://docs.python.org/2/library/exceptions.html#exception-hierarchy
try / except / else /finally
Il est possible de “sécuriser” une portion de code. Voire même d’intégrer l’erreur dans la logique du code.
try:
# bloc d'instruction dont on veux contrôler les exceptions émises
except ExceptionType1 as err1:
# Traitement de err1
# Typiquement:
# - on a une solution de repli dans le cas de err1
# OU
# - on sauve les meubles et on fait rebondir err1 (ou une nouvelle erreur)
except ExceptionType2 as err2:
# Traitement de err2
# ...
except ExceptionType3 as err3:
# Traitement de err3
# ...
else:
# Si aucune exception n'est émise dans le try
# alors ce bloc est exécuté
finally:
# Ce bloc sera exécuté quoi qu'il arrive
Exercices
Ecrire une fonction get(obj, index, default)
avec le même comportement que dict.get()
mais qui marche aussi bien pour les dict ou les listes .
Ecrire une fonction map_with_default(function, sequence, default)
qui marche comme map(function, sequence)
sauf que si une erreur est produite par function
lors de son évaluation, l’erreur n’est pas propagée. A la place, la valeur manquante est assignée à default
.