Aller au contenu principal

Exceptions

Progression

#Exceptions

À quoi ça sert ?

À quoi ça sert: signaler proprement les situations anormales et garantir la libération des ressources. Comment: try/except/else/finally, exceptions spécifiques, chaînage, et context managers pour le nettoyage.

Objectifs d’apprentissage

  • Utiliser try/except/else/finally selon l’intention (gestion d’erreur, nettoyage).
  • Lever des exceptions précises et les chaîner (raise ... from e).
  • Écrire des context managers (with) pour garantir la libération de ressources.
pythonpython
1try:2    1/03except ZeroDivisionError:4    print('division par zéro !')5finally:6    print('Toujours exécuté')
Spécificité d’abord

Interceptez des exceptions précises (ex: ValueError, KeyError) et laissez les autres remonter. Évitez except Exception sans re‑raise ciblé.

Lever des exceptions personnalisées:

pythonpython
1def racine(n: float) -> float:2    if n < 0:3        raise ValueError('n doit être >= 0')4    return n ** 0.55 6print(racine(9))

Chaînage et granularité:

pythonpython
1class PaymentError(Exception):2    pass3 4def pay():5    try:6        1/07    except ZeroDivisionError as e:8        raise PaymentError('échec paiement') from e9 10try:11    pay()12except PaymentError as e:13    print('Business error:', e.__cause__.__class__.__name__)

#Playground

Chargement de l’éditeur...

#Exercices

  • Écrire un parseur robuste pour des lignes a;b;c (skip lignes invalides, rapport d’erreurs).
  • Écrire un contexte timer() qui mesure la durée d’un bloc (via with).

#Pièges fréquents

  • except Exception: trop large masque des bugs; préférez des exceptions précises.
  • Ne pas oublier finally (ou context manager) pour libérer fichiers/verrous/sockets.
  • raise vs return dans finally: un return dans finally supprime l’exception — à éviter.

#Danger: return dans finally

pythonpython
1def f():2    try:3        1/04    finally:5        return 'masque l\'exception'  # à éviter6 7print(f())  # L'exception ZeroDivisionError est perdue !

Règle simple: ne pas retourner depuis finally. Faites les nettoyages, puis laissez l’exception remonter.

#Relancer proprement

pythonpython
1try:2    ouvrir_fichier()3except OSError as e:4    # Ajouter du contexte sans perdre la trace d'origine5    raise RuntimeError('échec ouverture fichier config') from e

#Nettoyages et context managers

Utilisez with pour garantir la fermeture/libération:

pythonpython
1from contextlib import contextmanager2 3@contextmanager4def timer():5    import time6    t0=time.perf_counter();7    try:8        yield9    finally:10        print(f"{(time.perf_counter()-t0)*1e3:.1f} ms")11 12with timer():13    sum(range(10_000))

#Quiz éclair

Lequel garantit l’exécution même en cas d’exception ?
Lequel garantit l’exécution même en cas d’exception ?