web-dev-qa-db-fra.com

Dois-je toujours spécifier un type d'exception dans les instructions `except`?

Lors de l’utilisation de PyCharm IDE, l’utilisation de except: sans type d’exception déclenche un rappel de IDE) indiquant que cette clause d’exception est Too broad.

Devrais-je ignorer ce conseil? Ou est-ce Pythonic de toujours spécifier le type d'exception?

81
HorseloverFat

Il est presque toujours préférable de spécifier un type d’exception explicite. Si vous utilisez une clause except: Naked, vous risquez de capturer des exceptions autres que celles que vous vous attendez à capturer. Cela peut masquer des bogues ou rendre plus difficile le débogage de programmes lorsqu'ils ne font pas ce que vous attendez.

Par exemple, si vous insérez une ligne dans une base de données, vous souhaiterez peut-être intercepter une exception indiquant que la ligne existe déjà afin de pouvoir effectuer une mise à jour.

try:
    insert(connection, data)
except:
    update(connection, data)

Si vous spécifiez un except: Nu, vous obtiendrez également une erreur de socket indiquant que le serveur de base de données est tombé. Il est préférable de ne capturer que les exceptions que vous savez manipuler - il est souvent préférable que le programme échoue au point d'exception plutôt que de continuer, mais de se comporter de manière étrange et inattendue.

Un cas où vous voudrez peut-être utiliser un simple except: Se trouve au plus haut niveau d'un programme que vous devez toujours exécuter, comme un serveur réseau. Mais alors, vous devez être très prudent pour enregistrer les exceptions, sinon il sera impossible de déterminer ce qui ne va pas. Fondamentalement, il ne devrait y avoir qu’un seul endroit dans un programme qui fait cela.

Un corollaire à tout cela est que votre code ne doit jamais faire raise Exception('some message') car il oblige le code client à utiliser except: (Ou except Exception: Qui est presque = aussi mauvais). Vous devez définir une exception spécifique au problème que vous souhaitez signaler (peut-être hériter d'une sous-classe d'exceptions intégrée telle que ValueError ou TypeError). Ou vous devriez lever une exception intégrée spécifique. Cela permet aux utilisateurs de votre code de ne prendre que les exceptions qu'ils souhaitent gérer.

76
babbageclunk

Vous ne devez pas ignorer les conseils de l'interprète.

À partir du PEP-8 Guide de style pour Python:

Lorsque vous interceptez des exceptions, mentionnez autant que possible des exceptions spécifiques au lieu d'utiliser une clause bare except:.

Par exemple, utilisez:

 try:
     import platform_specific_module 
 except ImportError:
     platform_specific_module = None 

Une clause bare except: intercepte les exceptions SystemExit et KeyboardInterrupt, ce qui rend plus difficile l'interruption d'un programme avec Control-C et peut dissimuler d'autres problèmes. Si vous voulez intercepter toutes les exceptions signalant des erreurs de programme, utilisez except Exception: (nu sauf équivaut à excepter BaseException :).

Une bonne règle consiste à limiter l’utilisation des clauses "sauf" nues à deux cas:

Si le gestionnaire d'exceptions doit imprimer ou consigner la trace; au moins l'utilisateur sera conscient qu'une erreur est survenue. Si le code doit effectuer un travail de nettoyage, laissez ensuite l'exception se propager vers le haut avec une levée. essayez ... peut enfin être un meilleur moyen de gérer cette affaire.

34
asheeshr

Non spécifique à Python this.

Le point essentiel des exceptions est de traiter le problème aussi près que possible de la cause.

Ainsi, vous conservez le code qui, dans des circonstances exceptionnelles, pourrait provoquer le problème et la résolution suivante.

Le problème, c'est que vous ne pouvez pas connaître toutes les exceptions qu'un code pourrait générer. Tout ce que vous pouvez savoir, c'est que s'il s'agit d'une exception dite fichier non trouvé, vous pouvez l'intercepter et demander à l'utilisateur d'en obtenir une qui annule ou annule la fonction.

Si vous tentez de contourner ce problème, quel que soit le problème rencontré dans votre routine de fichier (lecture seule, autorisations, UAC, pas vraiment un fichier PDF, etc.), tout le monde accédera à votre capture de fichier non trouvé, et votre utilisateur crie "mais c'est là, ce code est de la merde"

Maintenant, il existe quelques situations dans lesquelles vous pouvez tout attraper, mais elles doivent être choisies consciemment.

Elles sont interceptées, annulent certaines actions locales (telles que la création ou le verrouillage d'une ressource (ouvrir un fichier sur un disque pour écrire, par exemple), puis renvoyer l'exception pour être traitée à un niveau supérieur).

L'autre vous est que vous ne vous souciez pas de savoir pourquoi cela s'est mal passé. Impression par exemple. Vous avez peut-être un piège à tout point: vous dites qu'il y a un problème avec votre imprimante, résolvez-le et ne tuez pas l'application à cause de cela. De même, si votre code exécute une série de tâches distinctes à l’aide d’une planification, vous ne voudriez pas que tout disparaisse, car l’une des tâches a échoué.

Remarque Si vous procédez comme indiqué ci-dessus, je ne peux pas vous recommander une sorte de journalisation des exceptions, par exemple. essayez attraper la fin du journal, fortement.

8
Tony Hopkinson

Vous allez également attraper par exemple Control-C avec ça, alors ne le faites pas à moins de le "jeter" à nouveau. Cependant, dans ce cas, vous devriez plutôt utiliser "finalement".

3
Ulrich Eckhardt

Voici les endroits où j'utilise sauf sans type

  1. prototypage rapide et sale

C'est l'utilisation principale dans mon code pour les exceptions non contrôlées

  1. fonction principale () de niveau supérieur, où je me connecte à chaque exception non capturée

J'ajoute toujours ceci, pour que le code de production ne renverse pas stacktraces

  1. entre les couches d'application

J'ai deux façons de le faire:

  • Première façon de le faire: lorsqu'une couche de niveau supérieur appelle une fonction de niveau inférieur, elle encapsule les appels dans des exceptions typées pour gérer les exceptions "de niveau supérieur". Mais j'ajoute une instruction générique sauf, pour détecter les exceptions de niveau inférieur non gérées dans les fonctions de niveau inférieur.

Je le préfère de cette façon, je trouve plus facile de détecter les exceptions qui auraient dû être interceptées correctement: je "vois" mieux le problème quand une exception de niveau inférieur est enregistrée par un niveau supérieur

  • Seconde façon de procéder: chaque code des fonctions de niveau supérieur des couches de niveau inférieur est enveloppé dans un code générique sauf, il capture toutes les exceptions non gérées sur ce calque spécifique.

Certains collègues préfèrent cette méthode, car elle conserve les exceptions de niveau inférieur dans les fonctions de niveau inférieur, où elles "appartiennent".

3
nipil

Toujours spécifier le type d'exception, il existe de nombreux types que vous ne voulez pas capturer, comme SyntaxError, KeyboardInterrupt, MemoryError etc.

3
Pavel Anossov