def base_exception_handling():
    """Code de base pour gérer une exception."""
    try:
        15 / 0
    except ZeroDivisionError:
        print("Nous avons eu une erreur de division par zéro !")
    except Exception:
        print("Exception non prise en charge !")


def exception_with_else():
    """
    Gérer une exception, avec la clause else.

    La clause else contient du code qui est exécuté si tout se passe
    bien.

    """
    try:
        15 / 1
    except ZeroDivisionError:
        print("Division par zéro !")
    else:
        print("Tout s'est bien passé !")


def exception_with_finally():
    """
    Gérer une exception, avec la clause finally.

    Le bloc de la clause finally est toujours exécuté,
    quand une exception est levée ou que tout se passe bien.
    le bloc finally est même exécuté si vous essayez de faire un
    `return` dans votre bloc `try`, alors que pourtant la directive
    `return` interrompt normalement l'exécution de la fonction.
    Cas de figure : fermer un fichier ouvert quoi qu'il arrive.

    """
    try:
        15 / 0
    except ZeroDivisionError:
        print("Division par zéro !")
        return None
    finally:
        print("Pas si vite, monsieur return !")


def raise_exception():
    """
    Lever manuellement une exception simple.

    Si vous voyez une erreur dans la console, c'est normal.

    """
    raise ValueError("Valeur incorrecte.")


if __name__ == "__main__":
    base_exception_handling()
    exception_with_else()
    exception_with_finally()
    raise_exception()
