Forum Programmation.python Comment gérer correctement les exceptions

Posté par . Licence CC by-sa
Tags : aucun
2
3
mai
2016

Salut
Je code souvent des petits scripts python pour moi.
Généralement, je ne me soucie pas trop des exceptions.
Car je lance ces script manuellement et sais interpréter les exceptions.

Aujourd'hui, je dois fournir un script à un tiers, et tente de gérér les exceptions afin que les erreurs apparaissent correctement dans un fichier de traces :
016-05-03 16:04:59,103 - ERROR - opentextortg.py - 137 - Error in config file : No option 'field_search' in section: 'specific'

Je me rends compte que j'ai des try/except quasiment partout
Toutes mes lignes sont dans des sections try/except.

J'ai lu pas mal de bouquins sur python.
Ai je loupé quelque chose ?
Y a-til de bonnes méthodes ?

Merci !

David.

  • # A priori...

    Posté par (page perso) . Évalué à 4.

    il faudrait

    1. regarder du côté du module logging,
    2. encapsuler le script dans une fonction, elle-même appelée au sein d'un bloc try/except générique.

    Plus exactement du côté de la configuration des logger, pour avoir un WatchedFileHandler, par exemple.
    Je n'ai pas le temps de donner un exemple.

    Pour aller très vite, question logging du pauvre mais qui marche rudement bien, je tiens à signaler le module "q".

    Bonne suite !

  • # logging + exceptions

    Posté par . Évalué à 2. Dernière modification le 03/05/16 à 20:23.

    Bonjour,

    Le module "logging" est très bien pour afficher les infos en cours fonctionnement, et pour afficher des messages d'erreur. En plus, tu peux fournir un fichier de configuration au logging, pour laisser l'utilisateur final affiner ses traces.
    logging peut écrire dans un fichier, dans stderr, envoyer les traces en réseau, envoyer des mail… ou tous à la fois si tu veux ! N'utilise pas les appels "looging.debug" directement mais utilise plutôt les loggers nommés:

        logger = logging.getLogger('mon_module')  # "mon_module" est défini dans le fichier de conf du logging
        DEBUG and logger.debug("Class::method() val = %s", val)  # ce message n'est affiché qu'en mode DEBUG

    (C'est la notation que j'utilise)

    Le système try/except global est pas mal non plus, il permet de formater les exceptions qui arrivent impromptues.

    N'hésite pas non plus à définir tes propres exceptions si tu as des trucs compliqués à tester, ça prend 2 lignes en python (on est pas chez java)

    Ne met pas des try/except partout, laisse passer les "plus grosses" (fichier, io…), au pire re-raise les :

        try:
            du_code_qui_casse()
        except IOError as e:
            logger.critical('Class::method() Ouch : %s, e)
            raise e  # re-raise l'exception après traçage. Si tu mets un try/except global, elle est tracée 2 fois

    Le mise au point de fichiers de logs est quelque-chose de compliqué, entre "trop de messages" et "pas assez de messages"… Ce qui est important pour les dév ne l'est pas forcément pour l'utilisateur, et réciproquement !
    Voila, bon courage !

    • [^] # Re: logging + exceptions

      Posté par . Évalué à 1.

      J'utilise déjà le module logging.
      Donc pas de soucis pour les traces.
      Ce qui me gène, ce sont les try/catch partout.
      Le code devient illisible.

      • [^] # Re: logging + exceptions

        Posté par . Évalué à 2. Dernière modification le 04/05/16 à 01:42.

        Des try/catch partout ce n'est pas forcement mauvais, s'ils sont tous utiles, certains programmes le nécessitent, dans ce les systématiser, les commenter abonnement et aérer le code permet de rendre le tout plus clair.

        Un try/catch utile permet de récupérer d'une erreur sans interrompre le programme, genre l'utilisateur a entré une valeur incorrecte, re-demander à l'utilisateur d'entrer la valeur.

        Si c'est une erreur fatale, le try/catch "global" suffira à la logger.

        Y reste plus qu'à faire le tri.

        • [^] # Re: logging + exceptions

          Posté par (page perso) . Évalué à 2.

          Le try/except local permet aussi, dans le cadre d'une utilisation par des tiers, de préciser des erreurs et de donner des pistes vers les sources de problème.

          Par exemple, tu lis un fichier de configuration et tentes d'accéder à une valeur qui y est absente. Par défaut l'accès lève un KeyError. Tu peux intercepter l'erreur, logguer un "Missing configuration key %s in file %s", puis mettre un raise pour remonter l'erreur au dessus. L'utilisateur aura son exception, avec tout le traceback, mais il aura en plus une piste vers où chercher l'origine de l'erreur.

          Une chose surtout: ne jamais passer une exception d'erreur en silence, toujours la tracer quelque part, et si on n'a pas de solution de résolution du problème dans le bloc de traitement, alors remonter l'exception au dessus.

          Python 3 - Apprendre à programmer en Python avec PyZo et Jupyter Notebook → https://www.dunod.com/sciences-techniques/python-3

    • [^] # Re: logging + exceptions

      Posté par (page perso) . Évalué à 2.

      Pour remonter l'exception dans le traitement du bloc except, c'est pas raise sans argument ?

      Le raise avec un argument risque de te casser le traceback en considérant que l'exception est levée dans le bloc de traitement.

      Python 3 - Apprendre à programmer en Python avec PyZo et Jupyter Notebook → https://www.dunod.com/sciences-techniques/python-3

  • # Gestion des exceptions

    Posté par (page perso) . Évalué à 2.

    La gestion des exceptions, c'est pas seulement pour logguer les erreurs, c'est aussi pour essayer de rattraper ces exceptions si possible. Et dans les faits, il y a quand même énormément d'exceptions qui peuvent être rattrapées ou contournées. Donc je trouve pas cela mauvais d'avoir des try/except partout. Essaie juste de bien réfléchir à ce que chaque exception signifie, et essaie d'écrire du code spécifique pour gérer le problème, si possible. Je ne serais pas étonné si une bonne moitié de tes try/except le permettent plutôt que de simplement laisser une trace de log.

    Quant au fait d'en avoir plein, bienvenu dans la programmation sérieuse! Un bon programme a toujours énormément plus de code de gestion d'erreur, contrairement à des exemples de bouquins effectivement. D'ailleurs j'ai toujours trouvé irresponsables les bouquins qui mettent de côté la gestion d'erreur dans les exemples, et se contentent d'en faire un chapitre à part, comme si c'était juste une fonctionnalité comme une autre (que l'on peut donc ignorer éventuellement).
    Les premiers chapitres, éventuellement, mais une fois expliqués les exceptions, tous les exemples suivants devraient intégrer ces dernières.

    Conclusion:

    Y a-til de bonnes méthodes ?

    Oui, gère tes exceptions. :-)
    Pour le reste, tu peux aérer et mettre des commentaires, comme d'autres le conseillent, mais ne te préoccupe pas d'avoir un "beau code" sans exception. En fait c'est une question d'habitude: très probablement à force, par habitude, le beau code te paraîtra être ton code solide, c'est à dire celui qui gère bien les exceptions et ne crashe pas pour un rien.

    Film d'animation libre en CC by-sa/Art Libre, fait avec GIMP et autre logiciels libres: ZeMarmot [ http://film.zemarmot.net ]

  • # Question un peu floue

    Posté par (page perso) . Évalué à 2.

    Globalement les autres commentaires ont déjà dit ce que je pensais globalement sur les exceptions ; à savoir: selon les cas tu vas en avoir plein pour gérer finement les erreurs et les rattraper, ou bien les attraper plus globalement pour des erreurs plus fatales.

    Mais dans l'absolu sans voir ton code (ou une partie pertinente) il n'est pas forcément évident de donner une réponse satisfaisante:

    • S'agit-il principalement d'erreur système ? Les message te semblent abscons pour l'utilisateur ?
    • S'agit-il d'exceptions "algorithmiques" (KeyError, ValueError, TypeError…) ? auquel cas il y a souvent des alternatives plus courtes et aussi robustes que raisonner par exception.
    • S'agit-il d'exception "Maison" ?

    Je rajouterai que Python possède un arsenal d'outils efficaces permettant de factoriser le code si c'est l'aspect répétitif de ton code qui te gène.

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.