Sobes.tech
Middle

Comment fonctionnent les exceptions imbriquées en Python?

sobes.tech IA

Réponse de l'IA

Les exceptions imbriquées, également appelées chaînage d'exceptions, permettent de conserver des informations sur l'exception précédente lors de l'apparition d'une nouvelle. Cela est utile pour le débogage et la compréhension des causes de l'erreur.

Dans Python 3, par défaut, lorsqu'une nouvelle exception se produit dans un bloc except ou finally, l'exception d'origine est automatiquement liée à la nouvelle.

Cette liaison est stockée dans l'attribut __cause__ de la nouvelle exception.

Une liaison explicite peut être effectuée à l'aide du mot-clé raise from.

# Exemple de liaison automatique
def divide(a, b):
    try:
        return a / b
    except TypeError:
        # Lors du traitement de TypeError, une autre exception peut survenir
        # L'exception d'origine (TypeError) sera liée à la nouvelle
        raise ValueError("Type d'opérandes incorrect")

try:
    divide("a", 0)
except ValueError as e:
    # e.__cause__ contiendra un TypeError
    print(f"Erreur: {e}")
    if e.__cause__:
        print(f"Cause: {e.__cause__}")

print("-" * 20)

# Exemple de liaison explicite avec raise from
class CustomError(Exception):
    pass

def tricky_function():
    try:
        # Tentative de division par zéro, génère ZeroDivisionError
        result = 1 / 0
    except ZeroDivisionError as original_exc:
        # Créer une nouvelle exception et la lier à l'originale
        raise CustomError("Erreur lors du calcul") from original_exc

try:
    tricky_function()
except CustomError as e:
    # e.__cause__ contiendra ZeroDivisionError
    print(f"Erreur: {e}")
    if e.__cause__:
        print(f"Cause: {e.__cause__}")

print("-" * 20)

# Suppression de la liaison avec raise ... from None
try:
    try:
        # Exception d'origine
        raise ValueError("Erreur d'origine")
    except ValueError:
        # Lors du traitement de ValueError, une autre exception survient,
        # mais la liaison est supprimée
        raise TypeError("Nouvelle erreur") from None
except TypeError as e:
    # e.__cause__ sera None
    print(f"Erreur: {e}")
    if e.__cause__ is None:
        print("Raison non spécifiée.")

Le mot-clé raise sans arguments relance l'exception la plus récente.

# Exemple de relance d'exception
def process_data(data):
    try:
        # Supposons que quelque chose peut mal tourner ici
        if not data:
            raise ValueError("Données manquantes")
        print("Données traitées")
    except ValueError:
        print("Capture de ValueError")
        # Relancer la même exception
        raise

try:
    process_data("")
except ValueError as e:
    print(f"Exception relancée capturée: {e}")

Les exceptions imbriquées améliorent la lisibilité des traces d'erreur et aident à localiser plus rapidement la cause profonde du problème.