SunuLab
Notre savoir
CoursAvancé12 min de lecture

Erreurs et exceptions

Lire un traceback, rattraper une erreur avec try, et déboguer méthodiquement

§1.Deux familles d'erreurs

Les erreurs de SYNTAXE : ton texte n'est pas du Python. Un guillemet manquant, un deux-points oublié. Python refuse d'exécuter quoi que ce soit — même la première ligne. Elles sont pénibles mais faciles : le message pointe l'endroit.

Les erreurs d'EXÉCUTION : le programme est valide, il démarre, et il casse en cours de route. Diviser par zéro, convertir « bonjour » en nombre, lire un index qui n'existe pas. On les appelle des EXCEPTIONS.

Il existe une troisième famille, la pire : les erreurs de LOGIQUE. Le programme tourne sans broncher et donne un résultat faux. Aucun message ne t'avertit — seul un test bien choisi peut les révéler.

Relire un traceback

Trois informations, toujours les mêmes, à lire du BAS vers le HAUT.

text
Traceback (most recent call last):
File "<stdin>", line 7, in <module>
File "<stdin>", line 3, in moyenne
ZeroDivisionError: divide by zero

La DERNIÈRE ligne dit ce qui s'est passé : une division par zéro. Juste au-dessus, l'endroit exact : ligne 3, dans la fonction moyenne. Encore au-dessus, qui l'a appelée : la ligne 7. On lit donc de bas en haut — du symptôme vers son origine.

§3.Les exceptions les plus courantes

ExceptionCe qui s'est passéExemple typique
ZeroDivisionErrorDivision par zéroMoyenne d'une liste vide
ValueErrorBon type, mauvaise valeurint("bonjour")
TypeErrorMauvais type"3" + 5
IndexErrorIndex hors limitesliste[10] sur 3 éléments
KeyErrorClé absente d'un dictionnairenotes["Inconnu"]
NameErrorNom inconnuFaute de frappe sur une variable
AttributeErrorMéthode inexistante pour ce typeun entier auquel on demande .upper()

§4.Rattraper une exception : try / except

Une exception non rattrapée arrête le programme. Parfois c'est ce qu'on veut. Mais quand l'erreur est PRÉVISIBLE — un utilisateur qui tape n'importe quoi, un fichier absent — mieux vaut la traiter proprement.

Le bloc try contient le code risqué ; le bloc except dit quoi faire si ça casse. Si rien ne casse, le except est simplement ignoré.

Une saisie qui ne plante pas
python
def lire_entier(texte):
try:
return int(texte)
except ValueError:
return None
print(lire_entier("42"))
print(lire_entier("bonjour"))
print(lire_entier("3.5"))
Résultat : 42 None None

int("3.5") échoue aussi : ce n'est pas l'écriture d'un ENTIER. La fonction renvoie None dans les deux cas d'échec, laissant l'appelant décider quoi faire — plutôt que d'imposer un message d'erreur.

Plusieurs cas, et le nettoyage
python
def diviser(a, b):
try:
resultat = a / b
except ZeroDivisionError:
print("division par zéro")
return None
except TypeError:
print("il faut des nombres")
return None
else:
print("calcul réussi")
return resultat
finally:
print("-- terminé --")
print(diviser(10, 2))
print(diviser(10, 0))
Résultat : calcul réussi -- terminé -- 5.0 division par zéro -- terminé -- None

else s'exécute si AUCUNE exception n'a eu lieu. finally s'exécute dans TOUS les cas, succès comme échec — c'est là qu'on referme un fichier ou une connexion. Remarque qu'il tourne même après le return.

Provoque et rattrape
Chargement de l'éditeur Python…

§9.Lever ses propres exceptions

Quand ta fonction reçoit quelque chose d'incohérent, elle a deux choix : renvoyer une valeur spéciale comme None, ou signaler franchement le problème avec raise.

raise est souvent le meilleur choix. Renvoyer None laisse l'erreur se propager silencieusement et se manifester bien plus loin, à un endroit qui n'a rien à voir. Une exception, elle, s'arrête immédiatement au bon endroit et dit ce qui ne va pas.

raise, et une exception sur mesure
python
class NoteInvalide(Exception):
pass
def valider(note):
if not isinstance(note, (int, float)):
raise TypeError("une note doit être un nombre")
if note < 0 or note > 20:
raise NoteInvalide("note hors barème : " + str(note))
return note
for essai in [15, 25, "douze"]:
try:
print("ok :", valider(essai))
except NoteInvalide as e:
print("refusée ->", e)
except TypeError as e:
print("type ->", e)
Résultat : ok : 15 refusée -> note hors barème : 25 type -> une note doit être un nombre

Une exception personnalisée n'est qu'une classe qui hérite d'Exception — trois mots suffisent. Le as e récupère l'objet exception, dont l'affichage donne le message. Nommer ses erreurs rend le code bien plus lisible que des codes de retour.

§11.Déboguer méthodiquement

Face à un programme qui ne fait pas ce qu'on veut, le réflexe naturel est de modifier au hasard jusqu'à ce que ça marche. C'est le plus mauvais réflexe : on finit par masquer le symptôme sans comprendre la cause, et le bug revient plus tard.

La méthode qui fonctionne est celle du scientifique : formuler une hypothèse précise, la tester, en tirer une conclusion. Chaque test doit éliminer une possibilité.

§12.La démarche, dans l'ordre

  1. Lis le traceback en entier
    Le type, la ligne, le message. La réponse y est très souvent.
  2. Reproduis de façon fiable
    Trouve le plus petit cas qui déclenche le problème. Un bug qu'on sait reproduire est à moitié résolu.
  3. Formule une hypothèse
    « Je pense que ma liste est vide à ce moment-là. » Une phrase vérifiable, pas une impression.
  4. Vérifie avec un print
    Affiche la valeur ET son type juste avant la ligne qui casse. Le type révèle la moitié des bugs.
  5. Conclus
    Hypothèse confirmée : corrige. Infirmée : passe à la suivante. Jamais au hasard.
  6. Retire les print de débogage
    Ou remplace-les par un vrai test, qui vérifiera automatiquement que le bug ne revient pas.
Le print qui sauve

Afficher la valeur ne suffit pas toujours — c'est souvent le TYPE qui trahit le problème.

python
notes = ["12", "15", "9"] # lues depuis une saisie
print("valeur :", notes[0])
print("type :", type(notes[0]))
# total = sum(notes) -> TypeError : ce sont des chaînes !
total = sum(int(n) for n in notes)
print("total :", total)
Résultat : valeur : 12 type : <class 'str'> total : 36

À l'affichage, « 12 » et 12 sont indiscernables. type() lève le doute immédiatement. C'est le premier réflexe quand un calcul donne un résultat absurde.

Trouve le bug

Ce programme tourne sans erreur, et pourtant son résultat est faux. Applique la méthode.

Chargement de l'éditeur Python…

À retenir

  • Syntaxe : rien ne démarre. Exécution : ça casse en route. Logique : ça tourne et c'est faux — le pire.
  • Un traceback se lit du BAS vers le HAUT : le type d'abord, puis l'endroit, puis qui a appelé.
  • try / except rattrape une erreur PRÉVISIBLE ; else si tout va bien, finally dans tous les cas.
  • N'écris jamais except: tout seul — tu masquerais tes propres fautes de frappe.
  • raise signale franchement une donnée incohérente, là où renvoyer None laisse l'erreur se propager.
  • Une exception sur mesure tient en deux lignes : class MonErreur(Exception): pass
  • Déboguer : hypothèse, print de la valeur ET du type, conclusion. Jamais au hasard.
Mots-cléserreurexceptiontryexceptraisetracebackdébogageValueError