OUJOOD.COM
Python propose une quarantaine d'exceptions intégrées : ValueError, TypeError, FileNotFoundError… Elles couvrent les erreurs génériques. Mais dès que votre programme a sa propre logique métier — un compte bancaire qui ne peut pas être négatif, un âge qui doit rester dans une plage raisonnable, un identifiant qui doit respecter un format précis — les exceptions intégrées ne suffisent plus. Elles ne disent pas ce qui s'est passé dans votre contexte.
Les exceptions personnalisées règlent ce problème. Ce sont des classes Python qui héritent de Exception. Elles permettent de nommer les erreurs propres à votre application, de leur attacher des informations utiles, et de les intercepter précisément sans attraper tout le reste.
Rappel : comment fonctionne une exception en Python
Avant de créer les vôtres, voici comment Python gère les erreurs. Quand une instruction échoue, Python lève une exception avec raise. Le bloc try/except permet de l'intercepter et de réagir proprement.
try:
resultat = 10 / 0
except ZeroDivisionError:
print("Division par zéro impossible.")
# Résultat : Division par zéro impossible.
# On peut aussi lever une exception manuellement
age = -5
if age < 0:
raise ValueError("L'âge ne peut pas être négatif.")
Créer une exception personnalisée simple
Une exception personnalisée est une classe qui hérite de Exception. Dans sa forme la plus simple, elle n'a besoin d'aucun contenu — le nom de la classe suffit à identifier l'erreur.
# Définition d'une exception personnalisée class AgeInvalideError(Exception): pass # Utilisation def verifier_age(age): if age < 0 or age > 150: raise AgeInvalideError(f"Âge invalide : {age}") return age try: verifier_age(-3) except AgeInvalideError as e: print("Erreur :", e) # Résultat : Erreur : Âge invalide : -3
Le mot-clé pass indique que la classe ne définit rien de plus que ce qu'elle hérite. C'est suffisant dans beaucoup de cas : le nom de l'exception est déjà une information en soi.
Ajouter un message et des attributs personnalisés
Quand vous avez besoin de transporter plus d'informations avec l'erreur — le code d'erreur, la valeur fautive, un lien vers la documentation — définissez un constructeur __init__.
class SoldeInsuffisantError(Exception):
def __init__(self, solde, montant):
self.solde = solde
self.montant = montant
super().__init__(
f"Solde insuffisant : vous avez {solde}€, "
f"vous tentez de retirer {montant}€."
)
def retirer(solde, montant):
if montant > solde:
raise SoldeInsuffisantError(solde, montant)
return solde - montant
try:
retirer(50, 120)
except SoldeInsuffisantError as e:
print(e)
print(f"Manque : {e.montant - e.solde}€")
# Résultat :
# Solde insuffisant : vous avez 50€, vous tentez de retirer 120€.
# Manque : 70€
L'appel à super().__init__(message) transmet le message d'erreur à la classe parente Exception, ce qui permet de l'afficher normalement avec print(e).
Organiser ses exceptions en hiérarchie
Quand un projet grossit, il est utile de regrouper les exceptions liées sous une exception parente commune. Cela permet d'attraper soit une erreur précise, soit toute la famille d'un coup.
# Exception parente pour toute l'application class AppError(Exception): pass # Exceptions spécifiques qui héritent d'AppError class UtilisateurInexistantError(AppError): pass class MotDePasseIncorrectError(AppError): pass # On peut attraper une erreur précise... try: raise MotDePasseIncorrectError("Mot de passe erroné.") except MotDePasseIncorrectError as e: print("Authentification échouée :", e) # ...ou toute la famille d'un coup try: raise UtilisateurInexistantError("Utilisateur 'bob' introuvable.") except AppError as e: print("Erreur applicative :", e) # Résultat : Erreur applicative : Utilisateur 'bob' introuvable.
Lever une exception depuis une autre exception
Python permet d'enchaîner les exceptions avec raise ... from .... C'est utile quand vous interceptez une erreur bas niveau et que vous voulez la transformer en erreur métier, tout en conservant la trace de l'erreur originale.
class FichierConfigError(Exception):
pass
def charger_config(chemin):
try:
with open(chemin) as f:
return f.read()
except FileNotFoundError as e:
raise FichierConfigError(
f"Impossible de charger la config : {chemin}"
) from e
try:
charger_config("/chemin/inexistant/config.json")
except FichierConfigError as e:
print(e)
# Résultat : Impossible de charger la config : /chemin/inexistant/config.json
# Python affiche aussi la cause originale (FileNotFoundError) dans le traceback
Bonnes pratiques
Quelques règles simples pour des exceptions propres et maintenables :
- Nommez vos exceptions avec le suffixe
Error— c'est la convention Python :ValidationError,ConnexionError,FormatError. - Héritez de
Exception, pas deBaseException—BaseExceptionest la racine de tout, y comprisKeyboardInterruptetSystemExit. L'attraper accidentellement peut bloquer l'arrêt du programme. - Créez une exception parente par module ou domaine — cela simplifie les
exceptdans le code appelant. - Ne créez pas une exception pour chaque cas — si
ValueErrorouTypeErrordécrit déjà l'erreur clairement, utilisez-les.
# Structure recommandée pour un projet Python class MonProjetError(Exception): """Exception de base pour MonProjet.""" pass class ValidationError(MonProjetError): """Données invalides.""" pass class RessourceIntrouvableError(MonProjetError): """Ressource demandée absente.""" pass # Dans le code métier def trouver_produit(id_produit, catalogue): if id_produit not in catalogue: raise RessourceIntrouvableError( f"Produit '{id_produit}' absent du catalogue." ) return catalogue[id_produit] catalogue = {"P001": "Clavier", "P002": "Souris"} try: produit = trouver_produit("P099", catalogue) except RessourceIntrouvableError as e: print(e) # Résultat : Produit 'P099' absent du catalogue.
Par carabde | Mis à jour le 21 avril 2026