Aller au contenu

Exceptions#

courant

try / except / else / finally#

try:
    resultat = 10 / diviseur
except ZeroDivisionError:
    print("division par zéro")
except (TypeError, ValueError) as e:
    print(f"erreur : {e}")
else:
    print("aucune exception levée")   # exécuté seulement si pas d'exception
finally:
    print("toujours exécuté")           # nettoyage (fermeture ressource, etc.)

Hiérarchie des exceptions courantes#

BaseException
 ├── KeyboardInterrupt        (Ctrl+C — ne jamais l'attraper par accident)
 ├── SystemExit                (sys.exit())
 └── Exception                 (toutes les erreurs « normales »)
      ├── ArithmeticError
      │    ├── ZeroDivisionError
      │    └── OverflowError
      ├── LookupError
      │    ├── IndexError
      │    └── KeyError
      ├── OSError
      │    ├── FileNotFoundError
      │    ├── PermissionError
      │    └── IsADirectoryError
      ├── ValueError            (bon type, valeur inexploitable : int("abc"))
      ├── TypeError             (mauvais type : "a" + 1)
      ├── AttributeError
      ├── NameError
      └── StopIteration

Attraper une exception attrape aussi toutes ses sous-classes : except LookupError: intercepte IndexError et KeyError, except OSError: intercepte FileNotFoundError.

Exception.__mro__          # remonter la chaîne d'héritage d'une exception
issubclass(KeyError, LookupError)   # True

Piège

Ne jamais utiliser except: nu (attrape aussi KeyboardInterrupt, SystemExit). Toujours préciser le type, ou au minimum except Exception:.

Lever une exception#

def diviser(a, b):
    if b == 0:
        raise ZeroDivisionError("b ne peut pas être nul")
    return a / b

raise ValueError("message") from erreur_originale   # chaînage explicite

Exceptions personnalisées#

class SoldeInsuffisantError(Exception):
    """Levée quand un retrait dépasse le solde disponible."""

def retirer(compte, montant):
    if montant > compte.solde:
        raise SoldeInsuffisantError(f"solde {compte.solde} < {montant}")

assert#

assert age >= 0, "l'âge ne peut pas être négatif"

Désactivé si Python est lancé avec -O : ne pas l'utiliser pour valider des entrées utilisateur, seulement pour du débogage / des invariants internes.

re-lever une exception#

try:
    ...
except ValueError:
    log(...)
    raise            # relève la même exception (préserve la trace)