Les blocs try et except sont utilisés pour gérer les erreurs en Python (on parle d'exceptions).
Ils permettent d'anticiper un problème potentiel et d'exécuter du code alternatif en cas d'erreur afin d'éviter que le programme ne plante.
Cette gestion des erreurs est connue sous le nom de EAFP, qui signifie "Easier to Ask for Forgiveness than Permission", en français : il est plus simple de demander pardon que la permission.
En d'autres termes, avec le bloc try / except, on essaie d'exécuter une ligne de code, même si cette dernière est susceptible de déclencher une erreur. Si c'est le cas, on gère l'erreur (ou les erreurs) au cas par cas.
Prenons un exemple simple : une division par 0 est impossible et déclenche une erreur :
resultat = 10 / 0 print("Cette ligne ne sera jamais atteinte.") # Le programme s'arrête et affiche une erreur : # ZeroDivisionError: division by zero
Pour gérer cette erreur, on place le code à risque dans le bloc try, et si une erreur se produit Python arrête l'exécution du bloc try et passe à l'exécution du bloc except :
try: # On tente d'exécuter le code potentiellement problématique resultat = 10 / 0 except ZeroDivisionError: # Ce bloc ne s'exécute que si une ZeroDivisionError se produit print("Erreur : Division par zéro impossible !") print("Le programme continue son exécution normalement.")
Dans ce cas le programme ne plante pas, il va poursuivre son exécution tout en affichant un message clair.
À noter
Il est recommandé d'être précis dans le bloc except en spécifiant le type d'erreur que l'on s'attend à recevoir afin de ne pas masquer des erreurs inattendues.
# ✅ Conseillé try: nombre = int("abc") except ValueError: # On gère spécifiquement l'erreur de conversion print("Erreur : 'abc' ne peut pas être converti en nombre.") # ❌ Déconseillé try: nombre = int("abc") except: print("Toutes les erreurs sont récupérées ici !")
Il est important de s'attarder sur l'importance de ne pas mettre un bloc try / except sans préciser l'erreur à récupérer, car c'est une notion souvent peu comprise des débutants.
Mettre un bloc try / except sans spécifier le type d'erreur est en apparence pratique : comme on ne sait pas forcément d'avance toutes les erreurs qui peuvent être provoquées, on les attrapes toutes (comme les pokémons) et on est ainsi assuré que notre script ne plantera jamais !
Écrire :
try: valeur = int("abc") except: valeur = 0
semble anodin.
L’intention est de gérer l’erreur de conversion (ValueError).
Mais ce bloc attrape toutes les exceptions !
Avec un exemple plus concret, cela peut devenir très problématique et se transformer en un véritable cauchemar à débogger.
def lire_fichier(path): try: # Suppose qu'on ouvre un fichier et qu'on convertit son contenu en entier with open(path) as f: return int(f.read()) except: return 0
-
Si le fichier contient "abc", on a bien un ValueError, et retourner 0 est logique.
-
Mais si le fichier n’existe pas (FileNotFoundError), le except capture aussi cette erreur et retourne silencieusement 0.
👉 Résultat : on ne sait jamais que le fichier est manquant.
Dans un contexte réel (ex. facturation, configuration critique), ça peut conduire à de graves incohérences car une erreur de système est traitée comme une simple erreur de conversion.
Il est donc toujours important de limiter l’exception au cas prévu et de gérer ce cas en conséquence pour être certain de ce que notre script fera dans cette situation précise uniquement.
def lire_fichier(path): try: with open(path) as f: return int(f.read()) except ValueError: # Le fichier existe, mais son contenu n’est pas un entier, pas grave, on retourne un entier par défaut. return 0 except FileNotFoundError: # Le fichier est absent, là c'est plus grave, le fichier doit exister : on l'indique clairement et on arrête le programme. print("Fichier introuvable, veuillez le créer :", path) raise
Avec le code ci-dessus, on gère séparément ces 2 erreurs.
-
Une erreur de conversion est gérée en douceur.
-
Une erreur système comme un fichier manquant est signalée distinctement et ne passe pas inaperçue.
else et finally
La structure try except peut être complétée par else et finally :
-
else : le code s'exécute uniquement si aucune erreur ne s'est produite dans try
-
finally : le code s'exécute dans tous les cas
try: # On demande deux nombres à l'utilisateur dividende = float(input("Entrez le nombre à diviser : ")) diviseur = float(input("Entrez le diviseur : ")) # On tente la division resultat = dividende / diviseur except ValueError: # S'exécute si l'utilisateur n'entre pas un nombre valide print("Erreur : Veuillez entrer des nombres valides.") except ZeroDivisionError: # S'exécute si l'utilisateur tente de diviser par zéro print("Erreur : La division par zéro est impossible.") else: # S'exécute SEULEMENT si aucune erreur n'a eu lieu dans le bloc 'try' print(f"Le résultat de la division est : {resultat}") finally: # S'exécute TOUJOURS, à la fin, peu importe le résultat print("--- Fin de la tentative de calcul. ---")
Attraper plusieurs exceptions à la fois
Il est possible de gérer plusieurs types d'exceptions avec un seul bloc except en les regroupant dans un tuple :
try: valeur = input("Entrez un nombre : ") resultat = 10 / int(valeur) except (ValueError, ZeroDivisionError): print("Erreur : L'entrée est invalide ou une division par zéro a eu lieu.")
Attraper toutes les exceptions
Il est possible de capturer toutes les erreurs, même si c'est fortement déconseillé :
try: resultat = "un" + 2 except Exception as e: print(f"Une erreur inattendue est survenue : {e}") # Une erreur inattendue est survenue : can only concatenate str (not "int") to str
L'alias as e permet de capturer l'erreur elle-même afin :
-
D'afficher un message d'erreur précis (comme dans notre exemple)
-
Enregistrer l'erreur dans un fichier de log