Introduction

La programmation système implique des interactions avec les périphériques de stockage ou le réseau, aux cours desquelles des erreurs peuvent survenir (erreur d’entrée-sortie ou de connexion par exemple). Ces erreurs imprévisibles (et qui ne surviennent pas lorsque le fonctionnement est nominal) sont appelées exceptions et doivent être traités.

Exemple

Cet exemple présente un exemple de traitement d’exceptions dans le cas d’un calcul d’écart type, avec un risque d’exception en cas de division par zéro.

Les instructions effectuant le calcul sont placées dans un bloc try, et l’exception (ZeroDivisionError) est traitée (message d’erreur et absence de résultat).

Rappel mathématiques statiques

L’écart type sert à mesurer à quel point des nombres sont “proches” ou “éloignés” entre eux, en se basant sur la moyenne comme point de référence. C’est la “moyenne des écarts à la moyenne”. Il se détermine en plusieurs étapes :

  • calcul de la somme des nombres ;
  • calcul de la moyenne des nombres ;
  • calcul de la sommes des écarts² à la moyenne : ∑(nombre - moyenne)² ;
  • calcul de la √moyenne des écarts (l’écart-type).

Code du programme

from typing import List, Optional

def ecart_type(tableau: List[float]) -> Optional[float]:
    nb = len(tableau)
    try:
        cumul = 0
        for val in tableau:
            cumul += val
        print("∑ valeurs : " + str(cumul)) #(debug)
        moyenne = cumul / nb               #exception si division par 0
        print("moyenne : " + str(moyenne)) #(debug)
        cumul = 0
        for val in tableau:
            cumul += (val - moyenne) ** 2  #rappel: x**2 = x²
        print("∑ écarts² : " + str(cumul)) #(debug)
        resultat = (cumul / nb) ** 0.5     #rappel: x**0.5 = √x
    except ZeroDivisionError:
        print("erreur: le tableau est vide")
        resultat = None                    #cf Optional
    return resultat

if __name__ == "__main__":
    print(ecart_type([]))                  #None
    e = ecart_type([12, 15, 17])
    print("ecart type : " + str(e))

Observations

Les instructions print selon qu’elles sont exécutées ou non permettent d’observer le traitement réalisé :

  • fonctionnement nominal : exécution de toutes les instructions du bloc try ;
  • exception : interruption du try et exécution du bloc except.

Remarques

  • Optional[type] permet d’indiquer que la donnée peut aussi être None (absente) — ici dans le cas d’une division par 0 (tableau vide).
  • Pour cette situation, il aurait été possible (voire souhaitable) de remplacer les blocs try/except par une alternative :
if nb != 0:
        #contenu du bloc try
    else:
        #contenu du bloc except

Syntaxe

Les instructions susceptibles Les instructions du programme doivent donc être rédigées sans tenir compte des potentielles erreurs à l’intérieur d’un bloc try, et le traitement des exceptions placé dans le (ou les) blocs except (catch dans d’autres langages de programmation) associés.

Les instructions du bloc try sont interrompues en cas d’exception et celles du bloc except sont alors exécutées.

Si une exception n’est pas capturée, c’est-à dire si elle se produit en dehors d’un bloc try, le programme est interrompu.

try:
    #instructions pouvant lever une exception
except TypeException:
    #traitement du premier type d'exception
except AutreType as e: #(e est une convention)
    #traitement d'un autre type avec détail (cf e) sur l'exception
finally: #bloc facultatif
    #instructions exécutées dans tous les cas

Il existe de nombreux types d’exceptions ; cf référence des exceptions en Python.