Gérer
les erreurs
Hiérarchie des exceptions, try/except, exceptions personnalisées, logging et débogueur.
Hiérarchie des exceptions
Toutes les exceptions héritent de BaseException. Attraper une classe parente attrape aussi toutes les classes filles.
Ne jamais faire except: ou except Exception: de façon aveugle — cela masque les erreurs. Toujours attraper le type d'exception le plus précis possible.
Ne jamais attraper SystemExit ni KeyboardInterrupt (Ctrl+C) — ils ne sont pas des erreurs de programme.
try / except / else / finally
try:
# Code susceptible de lever une exception
résultat = int(input("Entrez un nombre : "))
valeur = 100 / résultat
except ValueError:
# Saisie non convertible en int
print("Ce n'est pas un nombre valide.")
except ZeroDivisionError:
# Division par zéro
print("Division par zéro impossible.")
except (OSError, IOError) as e:
# Attraper plusieurs types, récupérer l'objet
print(f"Erreur I/O : {e}")
else:
# Exécuté SEULEMENT si aucune exception
print(f"Résultat : {valeur}")
finally:
# TOUJOURS exécuté (nettoyage)
print("Fin du bloc.")
| Bloc | Quand s'exécute-t-il |
|---|---|
try | Toujours en premier |
except | Si exception correspondante |
else | Si aucune exception dans try |
finally | Toujours, exception ou non |
Mettre le code "succès" dans else plutôt que dans try — cela évite d'attraper accidentellement les exceptions que else pourrait lever.
try:
données = charger_fichier()
except FileNotFoundError as e:
print(f"[LOG] Fichier manquant : {e}")
raise # re-lever SANS perdre la trace
Lever une exception
# Lever une exception standard
def diviser(a, b):
if b == 0:
raise ValueError("Le diviseur ne peut pas être zéro")
return a / b
# Chaîner les exceptions (Python 3)
try:
résultat = int("abc")
except ValueError as e:
raise RuntimeError("Échec du traitement") from e
# La traceback montrera les deux erreurs
# Supprimer la chaîne (si non pertinente)
raise RuntimeError("Échec") from None
Exceptions personnalisées
Créer ses propres exceptions améliore la lisibilité et permet des traitements spécifiques.
# Hiérarchie personnalisée
class AppErreur(Exception):
"""Classe de base pour les erreurs de l'application."""
pass
class ErreurValidation(AppErreur):
def __init__(self, champ: str, valeur, message: str):
self.champ = champ
self.valeur = valeur
super().__init__(f"[{champ}={valeur}] {message}")
class ErreurBD(AppErreur):
def __init__(self, requête: str, cause=None):
self.requête = requête
super().__init__(f"Échec requête : {requête}")
if cause: self.__cause__ = cause
# Utilisation
def valider_age(age: int):
if not (0 <= age <= 150):
raise ErreurValidation("age", age, "doit être entre 0 et 150")
try:
valider_age(-5)
except ErreurValidation as e:
print(f"Champ invalide : {e.champ}") # "age"
print(e) # "[age=-5] doit être entre 0 et 150"
Context managers — with
# Fichiers — fermeture automatique
with open("data.txt") as f:
contenu = f.read()
# f est fermé ici, même si exception
# Plusieurs contextes
with open("in.txt") as src, \
open("out.txt", "w") as dst:
dst.write(src.read())
from contextlib import contextmanager
@contextmanager
def chrono(label):
import time
début = time.perf_counter()
try:
yield # ← le bloc with s'exécute ici
finally:
durée = time.perf_counter() - début
print(f"{label}: {durée:.3f}s")
with chrono("Traitement"):
traiter_données()
Cheat sheet
Structure try
| try / except | Attraper une erreur |
| except X as e | Récupérer l'objet |
| else | Si aucune erreur |
| finally | Toujours exécuté |
| raise | Lever / re-lever |
| raise X from Y | Chaîner |
Exceptions courantes
| ValueError | Valeur incorrecte |
| TypeError | Mauvais type |
| KeyError | Clé dict absente |
| IndexError | Index hors limite |
| AttributeError | Attribut inexistant |
| FileNotFoundError | Fichier absent |
Bonnes pratiques
| Précis | except ValueError, pas Exception |
| Logging | logger.exception() dans except |
| Custom | Hériter de Exception |
| Contexte | with open() plutôt que try/finally |
| Re-lever | raise (sans arg) préserve la trace |
Pour les stratégies de débogage avancées (pdb, VS Code debugger, print/logging, erreurs fréquentes Python/JS/C), consultez la page dédiée :
🐛 Débogage — Guide complet ↗