Complément - niveau intermédiaire¶
L’instruction try est généralement assortie d’une une ou plusieurs clauses except, comme on l’a vu dans la vidéo.
Sachez que l’on peut aussi utiliser - après toutes les clauses except :
une clause
else, qui va être exécutée si aucune exception n’est attrapée ;et/ou une clause
finallyqui sera alors exécutée quoi qu’il arrive.
Voyons cela sur des exemples.
finally¶
C’est sans doute finally qui est la plus utile de ces deux clauses, car elle permet de faire un nettoyage dans tous les cas de figure - de ce point de vue, cela rappelle un peu les context managers.
Et par exemple, comme avec les context managers, une fonction peut faire des choses même après un return.
# une fonction qui fait des choses après un return
def return_with_finally(number):
try:
return 1/number
except ZeroDivisionError as e:
print(f"OOPS, {type(e)}, {e}")
return("zero-divide")
finally:
print("on passe ici même si on a vu un return")# sans exception
return_with_finally(1)on passe ici même si on a vu un return
1.0# avec exception
return_with_finally(0)OOPS, <class 'ZeroDivisionError'>, division by zero
on passe ici même si on a vu un return
'zero-divide'else¶
La logique ici est assez similaire, sauf que le code du else n’est exécuté que dans le cas où aucune exception n’est attrapée.
En première approximation, on pourrait penser que c’est équivalent de mettre du code dans la clause else ou à la fin de la clause try. En fait il y a une différence subtile :
The use of the
elseclause is better than adding additional code to thetryclause because it avoids accidentally catching an exception that wasn’t raised by the code being protected by thetry…exceptstatement.
Dit autrement, si le code dans la clause else lève une exception, celle-ci ne sera pas attrapée par le try courant, et sera donc propagée.
Voici un exemple rapide, en pratique on rencontre assez peu souvent une clause else dans un try :
# pour montrer la clause else dans un usage banal
def function_with_else(number):
try:
x = 1/number
except ZeroDivisionError as e:
print(f"OOPS, {type(e)}, {e}")
else:
print("on passe ici seulement avec un nombre non nul")
return 'something else'# sans exception
function_with_else(1)on passe ici seulement avec un nombre non nul
'something else'# avec exception
function_with_else(0)OOPS, <class 'ZeroDivisionError'>, division by zero
'something else'Remarquez que else ne présente pas cette particularité de “traverser” le return, que l’on a vue avec finally :
# la clause else ne traverse pas les return
def return_with_else(number):
try:
return 1/number
except ZeroDivisionError as e:
print(f"OOPS, {type(e)}, {e}")
return("zero-divide")
else:
print("on ne passe jamais ici à cause des return")# sans exception
return_with_else(1)1.0# avec exception
return_with_else(0)OOPS, <class 'ZeroDivisionError'>, division by zero
'zero-divide'Pour en savoir plus¶
Voyez le tutorial sur les exceptions dans la documentation officielle.