Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Industrial programming >> Python

Éviter les pièges courants : gestion d'exceptions correcte en Python

Éviter les pièges courants : gestion d exceptions correcte en Python

Je vois beaucoup de gens gérer les exceptions mal. Peut-être vous aussi. Cette situation vous est-elle familière ?

Vous écrivez du code, mais la bibliothèque utilisée peut lever une exception. Vous ne rappelez plus laquelle exactement. Tentant d'utiliser des blocs « catch-all » et passer au fun.

La pire façon de faire

Le pire : bloc try-except qui attrape tout. Par catch-all, je veux dire :

try:
    ...
except:
    pass

Ces blocs catch-all sont mauvais car :

  1. Vous n'avez aucune idée des autres exceptions qui pourraient être levées (plus tard).
  2. On cache l'exception en utilisant silencieusement pass au lieu de logger l'erreur.

De plus, except: vide attrape TOUT, y compris KeyboardInterrupt (Ctrl+C), SystemExit, et même NameError ! Ce code ne peut pas être arrêté proprement :

from time import sleep
while True:
    try:
        print("Essayez de m'arrêter")
        sleep(1)
    except:
        print("N'arrêtez... pas... moi maintenant !")

Essayez. Il faut fermer le terminal ou tuer le processus Python pour l'arrêter.

Une façon un peu meilleure d'attraper toutes les exceptions

En revanche, except Exception — bien que toujours rapide et sale pour attraper trop d'exceptions — permet au moins d'arrêter le processus proprement :

from time import sleep
while True:
    try:
        print("Essayez de m'arrêter")
        sleep(1)
    except Exception:
        print("Ok j'arrête !")

Avec except Exception, on n'attrape pas SystemExit, KeyboardInterrupt et semblables. Pourquoi ?

Toutes exceptions héritent de BaseException. Doc officielle : « Dans try avec clause except mentionnant classe particulière, cette clause gère aussi classes dérivées. » except: vide = except BaseException = attrape toutes exceptions possibles.

En contraste, classe Exception : « Toutes exceptions built-in non-système en dérivent. Exceptions utilisateur devraient aussi en dériver. »

C'est encore pire

Exemple : bibliothèque os pour répertoire courant. Mais faute de frappe :

import os
try:
    working_dir = os.getcdw()
    print(working_dir)
except:
    print('erreur')

os.getcdw n'existe pas, NameError levée. Au lieu d'échouer, except attrape, affiche 'erreur', programme continue malgré typo flagrante. Pas résolu par except Exception non plus !

Notre astuce étape 1 ne fixe pas tout. Que devrait-on faire ?

Attraper ce qu'on peut gérer

Phrase souvent entendue : attrapez ce que vous pouvez gérer. Beaucoup développeurs tentent de gérer exceptions directement, alors qu'il vaut souvent mieux laisser l'exception remonter à une partie du programme qui peut VRAIMENT la gérer.

Exemple : partie éditeur texte qui ouvre/charge fichiers, classe OpenFile. Si utilisateur demande ouverture fichier inexistant, soit on gère directement, soit on propage.

Ici, mieux vaut propager à l'appelant, car OpenFile ne sait pas à quel point cette exception est grave pour l'appelant. L'appelant peut gérer de plusieurs façons :

De toute façon, ce n'est pas à OpenFile de décider quoi faire pour FileNotFoundError.

Une exception doit-elle TOUJOURS être propagée ? Non. Exception possible gérable dans OpenFile : TimeoutError. On peut vouloir réessayer quelques fois, sans déranger l'appelant. C'est une exception que OpenFile PEUT gérer, donc OK de l'attraper et réessayer.

Conclusion

Vous ne devriez JAMAIS attraper plus d'exceptions que vous ne pouvez gérer. Blocs except fourre-tout = recette pour bugs et code imprévisible. En d'autres termes : attrapez ce que vous pouvez gérer.

Si vous codez avec mantra « attrapez ce que vous pouvez gérer », écrire blocs catch-all enfreint toutes les règles. Alors s'il vous plaît, arrêtez. Exercice : revisitez votre code existant et voyez s'il peut être amélioré avec cette connaissance !

Python

  1. Maîtriser les opérateurs Python : Guide complet
  2. Maîtriser les erreurs et exceptions intégrées de Python
  3. Maîtriser les exceptions personnalisées Python : guide pratique
  4. Récupérer la date et l'heure actuelles en Python : Guide pratique
  5. Maîtriser la gestion multi-exceptions en Java
  6. Maîtriser la formation GMAO : Engager les équipes et booster la rétention
  7. Fonction Python print() : Guide pratique avec exemples
  8. Dictionnaires Python : Ajout, mise à jour et gestion des paires clé/valeur
  9. Python print sans saut de ligne : maîtriser le paramètre end et autres techniques