Les exceptions (Try - Except)
Tout au long de ce tutoriel, je ne vous ai pas parlé d'une chose très importante en programmation.
Cette chose est que vous n'êtes pas seul sur terre (Quoi !!! Vous n'étiez pas au courant ??

).
Et oui quand vous programmer, la plupart du temps d'autres personnes utiliseront votre programme. Ceci en lui même est une bonne chose mais peut vite générer des problèmes.
Pourquoi ?
Car les autres personnes ne pensent pas forcement comme vous. Pour preuve, rappelez-vous toutes les fois où je vous ai dit que "si vous avez un programme différent du mien, cela ne prouve pas qu'il est faux, car il y a plus façon de coder un programme". Et s'il y a plusieurs façons de coder, c'est que l'on ne pense pas pareil.
Mes idées ne sont pas ceux des autres
Tout ceci nous indique que lorsque l'on programme, nous allons devoir essayer de penser comme tout le monde.
Pour penser comme tout le monde, nous allons devoir imaginer ceux que pourrais faire un utilisateur avec notre programme.
Prenons l'exemple du programme suivant :
nombre = eval (input("Un nombre s'il vous plait : "))
print ("Le carré de", nombre, "est égale à", nombre*nombre)
Ce programme demande un nombre à l'utilisateur, et affiche le carré de ce nombre. (rien de bien compliquer si vous avez suivit ce tutoriel).
Testez-le puis étudions des utilisateurs quelconques.
L'utilisateur 1 exécute le programme, tape 5 et voit apparaitre que sont carré est 25.
L'utilisateur 2 exécute le programme, tape 10 et voit apparaitre que sont carré est 100.
L'utilisateur 3 exécute le programme, tape 99999999999999999999999999999999999999 et voit apparaitre que sont carré est un super super grand nombre.
Quand vous avez testé ce programme, vous avez mis un grand nombre ??
Moi ce ne fut pas le cas, j'ai testé comme l'utilisateur 1.
Bon! même en mettant des grands nombres, il ne nous embête pas, c'est magnifique.
Allez on continue !!!
L'utilisateur 4 exécute le programme, tape sqrt(25) et voit apparaitre une belle erreur disant "NameError: name 'sqrt' is not defined". En tapant racine de 25, l'utilisateur à fait apparaitre un problème. Mais bon c'est normale qu'il râle, il s'attendait à un chiffre et non à du texte.
Comment y remédier ?
Hé bien! comme l'utilisateur à taper une fonction python qui appartient à la bibliothèque (module) math, on a cas l'importer.
from math import *
nombre = eval (input("Un nombre s'il vous plait : "))
print ("Le carré de", nombre, "est égale à", nombre*nombre)
Et là c'est parfais, il ne dit plus rien.
Maintenant voyons les utilisateurs suivant :
L'utilisateur 5 exécute le programme, tape cinq et voit lui aussi apparaitre une belle erreur. NameError: name 'cinq' is not defined. Cette erreur est la même que celle de l'utilisateur 4.
Pourtant on avait réglé cette erreur, comment ce fais-t-il quelle apparait de nouveau ?
Et bien non!!! Nous n'avons pas réglé le problème, nous avons seulement fais en sorte que python reconnaisse le texte qui est une fonction. Mais dans le cas de l'utilisateur 5, il n'est pas possible de faire reconnaitre le texte car 'cinq' n'existe pas.
Pour pouvoir éviter les erreurs, on peut utiliser les exceptions.
La commande try
Lorsque l'on sait que le programme pourra générer des erreurs à telle partie du code, on utilise les exceptions.
Les exceptions sont composées de 2 parties : try et except
On a vu que le premier exemple de code génère une erreur. Cette erreur est produite lors de l'utilisation du input.
Donc on va devoir utiliser une exception à ce niveau.
Comment on utilise une exception ?
Voyons avec la correction de l'exemple (ne le testez pas maintenant car il manque une partie):
try :
nombre = eval (input("Un nombre s'il vous plait : "))
print ("Le carré de", nombre, "est égale à", nombre*nombre)
Ce programme est exécuté comme s'il n'y avait pas de try.
Il commence par demander un nombre et affiche ensuite son carré si tout se passe bien.
Par contre si lors de la demande du nombre, il y a une erreur, au lieu d'afficher l'erreur et d'arrêter le programme, il fera une autre action.
Cette action doit être présente dans except
La commande except
except permet donc de spécifier une action de remplacement en cas d'erreur.
try :
nombre = eval (input("Un nombre s'il vous plait : "))
print ("Le carré de", nombre, "est égale à", nombre*nombre)
except :
print ("Vous n'avez pas donné de nombre correct, nous ne pouvons donc pas donner le carré")
try fonctionne toujours avec except.
Ce programme demande donc un nombre et affiche son carré. Mais s'il y a eu une erreur lors de la récupération de ce nombre, il affiche qu'il est impossible de donner le carré.
Ce qui serait mieux, c'est de refaire une demande tant que l'on n'a pas un nombre, on peut donc coder :
nombreIncorrect = True
while nombreIncorrect == True :
try :
nombre = eval (input("Un nombre s'il vous plait : "))
nombreIncorrect = False
except :
print ("Vous n'avez pas donné de nombre correct, nous ne pouvons donc pas donner le carré")
print ("Le carré de", nombre, "est égale à", nombre*nombre)
On créer une variable avec la valeur True pour indiquer que la proposition effectuée est incorrecte
Tant que la proposition (le nombre) est incorrecte, donc que nombreIncorrect est égal à True, on demande un nombre.
Comme on a initialisé la variable à True, on entre dans la boucle et demande le nombre. Si le nombre proposé est correcte on indique avec "nombreIncorrect = False" que l'on ne doit pas refaire un tour de boucle donc de reposer la question.
Sinon on affiche que le carre est impossible. Comme la variable n'a pas été modifiée la boucle recommence.
Quand on est sorti de la boucle, on est sûr que la variable nombre contient bien un nombre. On peut donc afficher le carré.
On peut aussi utiliser la méthode montrée en exemple dans la documentation de python :
while True :
try :
nombre = eval (input("Un nombre s'il vous plait : "))
break
except :
print ("Vous n'avez pas donné de nombre correct, nous ne pouvons donc pas donner le carré")
print ("Le carré de", nombre, "est égale à", nombre*nombre)
"While True :" ne s'arrête jamais, c'est une boucle infinie.
Donc on demandera toujours un nombre, sauf si on arrête la boucle avec break. Comme le break est dans le try, la boucle s'arrêtera seulement s'il n'y a pas d'erreur, c'est-à-dire que le nombre n'est pas incorrect.
Avec les exceptions, vous pouvez donc gérer les erreurs. Mais attention à ne pas les utiliser à tort et à travers.
Ne pas toujours utiliser les exceptions
Certains programmes auront des erreurs mais ne les indiqueront pas. Comme ces erreurs ne sont pas affichées, les exceptions ne servent à rien.
Prenons par exemple ce code :
chiffre = eval (input("Entrez un nombre entre 1 et 100"))
print ("Vous avez tapez", chiffre)
Si un utilisateur tape 101, aucune erreur n'est produite pourtant ce n'est pas ce que l'on veut.
Pour que vous voyiez bien de quoi je parle, je n'ai pas mis les exceptions pour savoir si c'est bien un nombre.
Voyons avec une exception :
try :
chiffre = eval (input("Entrez un nombre entre 1 et 100"))
print ("Vous avez tapez", chiffre)
except :
print ("Vous n'avez pas donné un nombre entre 1 et 100")
Le résultat obtenu est identique si on tape 101.
Le code qu'il faut faire pour avoir ce que l'on demande est :
chiffre = eval (input("Entrez un nombre entre 1 et 100"))
if chiffre >= 1 and chiffre <= 100:
print ("Vous avez tapez", chiffre)
else :
print ("Vous n'avez pas donné un nombre entre 1 et 100")
Pour quelle raison les exceptions ne marchent pas dans ce cas ???
Parce que l'erreur est une erreur logique. Donc s'il y a quelque chose qui ne va pas, c'est que l'on n'a pas dit (ou mal dit) au programme ce que l'on voulait avoir.
Les erreurs qui peuvent être corrigées par des exceptions sont des erreurs de syntaxe. Mais attention toutes les erreurs de syntaxe ne nécessitent pas d'exceptions. Par exemple si vous avez mis "pront" au lieu de "print", vous aurez une erreur de syntaxe mais celle-ci est corrigeable en mettant un i à la place du o.
Conclusion
Quand vous programmez, vous devez donc toujours penser à ce que pourrait faire les utilisateurs.
Vous pourrez corriger certaines erreurs de syntaxe avec les exceptions (try et except). try permet de faire la partie générant une possible erreur et except permet de faires des actions si celle-ci est générée.