426 votes

Pourquoi est - "à l'exception de: - passer" d'une mauvaise programmation de la pratique?

Je vois souvent des commentaires sur d'autres DONC des questions sur la façon dont l'utilisation de l' except: pass est déconseillée. Pourquoi est-ce mauvais? Parfois, j'ai juste ne se soucient pas ce que l'erreur et je veux juste continuer avec le code.

try:
    something
except:
    pass

Pourquoi utiliser un except: pass bloc mauvais? Ce qui fait mal, est-ce le fait que j' pass sur une erreur, ou que j' except toute erreur?

465voto

poke Points 64398

Comme vous l'avez deviné, il y a deux côtés à elle: la Capture de toute erreur en spécifiant aucun type d'exception après l' except, et il suffit de le transmettre sans prendre toute action.

Mon explication est "un peu" plus de temps-alors tl;dr, il se décompose à ceci:

  1. Ne pas attraper de toute erreur. Toujours spécifier les exceptions que vous êtes prêt à récupérer et des seuls à attraper les.
  2. Essayez d'éviter de la transmettre à l'exception des blocs. Sauf si explicitement souhaité, ce n'est généralement pas un bon signe.

Mais entrons dans les détails:

Ne pas prendre toute erreur

Lors de l'utilisation d'un try bloc, généralement, vous le faites parce que vous savez qu'il ya une chance de l'exception levée. En tant que tel, vous aussi vous avez déjà une idée approximative de ce qui peut se briser et qu'une exception peut être levée. Dans de tels cas, vous intercepter une exception parce que vous pouvez positivement récupérer . Cela signifie que vous êtes prêts pour l'exception et d'autres plan qui vous suivra dans le cas de cette exception.

Par exemple, lorsque vous demandez à l'utilisateur de saisir un nombre, vous pouvez convertir l'entrée à l'aide de int() qui pourrait soulever un ValueError. Vous pouvez facilement récupérer simplement en demandant à l'utilisateur d'essayer de nouveau, de sorte que la capture de l' ValueError et de demander à l'utilisateur de nouveau serait un plan approprié. Un autre exemple serait si vous voulez lire un peu de configuration à partir d'un fichier, et que le fichier arrive de ne pas exister. Parce que c'est un fichier de configuration, vous pourriez avoir une certaine configuration par défaut comme un secours, de sorte que le fichier n'est pas exactement nécessaire. Afin d'attraper un FileNotFoundError et simplement d'appliquer la configuration par défaut serait un bon plan ici. Maintenant, dans ces deux cas, nous avons une très spécifiques exception, nous attendent et ont également un plan spécifique pour la récupérer. En tant que tel, dans chaque cas, nous avons explicitement seulement except que certains exception.

Cependant, si nous étions à attraper tout ce qui, en plus des exceptions que nous sommes prêts à récupérer de-il ya aussi une chance que nous obtenons des exceptions que nous ne nous attendions pas, et qui, en fait, nous ne peut pas récupérer de; ou ne devrait pas s'en remettre.

Prenons l'exemple de fichier de configuration à partir de ci-dessus. Dans le cas d'un fichier manquant, nous avons appliqué notre configuration par défaut, et pourrait être décidé à un moment plus tard pour enregistrer automatiquement la configuration (donc la prochaine fois, le fichier existe). Imaginez maintenant nous obtenir un IsADirectoryError, ou un PermissionError à la place. Dans de tels cas, nous avons probablement ne souhaitez pas continuer; on pourrait encore s'appliquer à notre configuration par défaut, mais plus tard, on ne sera pas en mesure d'enregistrer le fichier. Et il est probable que l'utilisateur fait pour avoir une configuration personnalisée trop, en utilisant les valeurs par défaut n'est probablement pas souhaité. C'est pourquoi nous voulons dire à l'utilisateur tout de suite, et probablement interrompre l'exécution du programme. Mais ce n'est pas quelque chose que nous voulons faire quelque part profondément à l'intérieur de certaines petite partie de code; c'est quelque chose d'application au niveau de l'importance, elle doit être traitée dans le haut-de sorte que l'exception de la bulle.

Un autre exemple simple est également mentionné dans le Python 2 idiomes document. Ici, une simple faute de frappe existe dans le code qui provoque la rupture. Parce que nous sommes la capture de chaque exception, nous avons également attraper NameErrors et SyntaxErrors. Les deux sont des erreurs qui se produisent pour nous tous lors de la programmation; et les deux sont des erreurs que nous ne veulent absolument pas à inclure lors de l'envoi du code. Mais parce que nous avons également pris ceux, nous ne savons même pas qu'ils s'y sont produites et de perdre toute les aider à déboguer correctement.

Mais il y a aussi plus dangereux exceptions qui nous sont peu préparés. Par exemple SystemError est généralement quelque chose qui arrive rarement et qui ne nous permet pas vraiment de plan pour; cela signifie qu'il ya quelque chose de plus compliqué passe, quelque chose qui probablement nous empêche de poursuivre la tâche en cours.

Dans tous les cas, il est très peu probable que vous êtes prêts pour le tout dans une petite échelle une partie du code, donc c'est vraiment là que vous ne devez attraper les exceptions à vous y préparer. Certaines personnes suggèrent au moins attraper Exception qu'il ne sera pas inclure des choses comme SystemExit et KeyboardInterrupt qui, de par leur conception , sont à mettre fin à votre demande, mais je dirais que c'est encore beaucoup trop imprécise. Il n'y a qu'un seul endroit où j'ai personnellement accepter attraper Exception ou tout simplement aucune exception, et c'est en un seul globale au niveau de l'application gestionnaire d'exception qui a le seul but d'enregistrer toute exception, nous ne sommes pas préparés. De cette façon, on peut encore retenir un maximum d'informations sur les exceptions inattendues, que nous avons ensuite pouvez utiliser pour étendre notre code pour gérer ces explicitement (si l'on peut récupérer à partir de la mer), ou dans le cas d'un bug à créer des cas de test pour s'assurer qu'elle ne se reproduise pas. Mais bien sûr, cela ne fonctionne que si nous n'en avons jamais pris de ces exceptions, nous étions déjà en attend, de sorte que celles que nous n'avons pas s'attendre naturellement à bulles.

Essayez d'éviter de la transmettre à l'exception des blocs

Quand explicitement attraper une petite sélection des exceptions spécifiques, il existe de nombreuses situations dans lesquelles nous allons être bien tout simplement à ne rien faire. Dans de tels cas, la seule présence d' except SomeSpecificException: pass est tout simplement parfait. La plupart du temps si ce n'est pas le cas comme nous l'avons probablement besoin d'un peu de code liés au processus de récupération (comme mentionné ci-dessus). Ce peut être, par exemple, quelque chose que les tentatives de l'action, ou pour définir une valeur par défaut à la place.

Si ce n'est pas le cas si, par exemple, parce que notre code est déjà structuré de manière à répéter jusqu'à ce qu'il réussit, puis juste en passant est assez bon. En prenant notre exemple ci-dessus, nous pourrions demander à l'utilisateur d'entrer un nombre. Parce que nous savons que les utilisateurs aiment pas faire ce que nous lui demandons, nous pourrions juste de le mettre dans une boucle, en premier lieu, de sorte qu'il pourrait ressembler à ceci:

def askForNumber ():
    while True:
        try:
            return int(input('Please enter a number: '))
        except ValueError:
            pass

Parce que nous continuons à essayer jusqu'à ce qu'aucune exception n'est levée, nous n'avons pas besoin de faire quelque chose de spécial à l'exception de bloc, c'est très bien. Mais bien sûr, on peut dire que nous avons au moins l'envie de montrer à l'utilisateur des messages d'erreur pour lui dire pourquoi il doit répéter l'entrée.

Dans de nombreux autres cas, par contre, juste de passage dans un except est un signe que nous n'étions pas vraiment préparés pour l'exception, nous sommes à la chasse. Sauf ces exceptions sont simples (comme ValueError ou TypeError), et la raison pour laquelle nous pouvons passer est évident, essayez d'éviter de simplement de passage. Si il n'y a vraiment rien à faire (et que vous êtes absolument sûr), puis ajouter un commentaire pourquoi c'est le cas; sinon, développez le bloc except pour inclure certains code de récupération.

except: pass

Le pire délinquant est bien la combinaison des deux. Cela signifie que nous sommes volontiers la capture de toute erreur bien que nous ne sommes absolument pas préparés pour cela et nous aussi, ne pas faire quoi que ce soit. Vous au moins que vous voulez enregistrer l'erreur et probablement aussi sur-relance à toujours mettre fin à l'application (il est peu probable que vous pouvez continuer comme d'habitude après un MemoryError). Juste de passage mais ne sera pas seulement de garder l'application un peu la vie (selon l'endroit où vous attraper bien sûr), mais aussi jeter toutes les informations, rendant impossible de découvrir l'erreur, ce qui est particulièrement vrai si vous n'êtes pas le seul à découvrir.


De sorte que la ligne de fond est: Attraper les exceptions que vous attendez vraiment et sont prêts à les récupérer; tous les autres sont probablement des erreurs que vous devez corriger, ou quelque chose que vous n'êtes pas prêt de toute façon. En passant spécifiques des exceptions est très bien si vous n'avez pas vraiment besoin de faire quelque chose à leur sujet. Dans tous les autres cas, c'est juste un signe de présomption et d'être paresseux. Et vous voulez certainement à résoudre ce problème.

281voto

Aaron Digulla Points 143830

Le principal problème ici est qu'il ignore tout de l'erreur: de mémoire, le CPU est brûlant, l'utilisateur veut les arrêter, le programme se veut à la sortie, Jabberwocky est de tuer des utilisateurs.

C'est beaucoup trop. Dans votre tête, vous êtes en train de penser "je veux ignorer cette erreur réseau". Si quelque chose d' inattendu se passe mal, alors votre code silencieusement continue et les pauses dans le complètement imprévisible qu'on ne peut debug.

C'est pourquoi vous devriez vous limiter à ignorer uniquement certaines erreurs et de laisser le reste passe.

93voto

YS-L Points 3562

L'exécution de votre code pseudo littéralement n'a même pas donner aucune erreur:

try:
    something
except:
    pass

comme si c'est un bon morceau de code, au lieu de jeter un NameError. J'espère que ce n'est pas ce que vous voulez.

61voto

Aaron Hall Points 7381

Quand vous prenez une base de classe d'exception, vous attrapez chaque sous-classe. Si vous attrapez tous les cas, avec except:, vous allez prendre, chaque exception, ce qui peut causer votre programme à se comporter de façon inattendue sur un appel à l' exit() ou si l'utilisateur effectue une interruption de clavier.

Python Exception De La Hiérarchie

Voici une partie de l' Python exception de la hiérarchie (voir le lien pour l'ensemble de la hiérarchie):

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
      |    +-- MemoryError
      |    +-- NameError
      |    |    +-- UnboundLocalError
      |    +-- ValueError
      |         +-- UnicodeError
      |              +-- UnicodeDecodeError
      |              +-- UnicodeEncodeError
      |              +-- UnicodeTranslateError
       +-- ImportWarning
       +-- UnicodeWarning
       +-- BytesWarning

Ne faites pas cette

Si vous êtes en utilisant ce formulaire de gestion des exceptions:

try:
    something
except: # don't just do a bare except!
    pass

Alors vous ne serez pas en mesure d'interrompre votre something bloc avec Ctrl-C. Votre programme donnent sur chaque Exception à l'intérieur de l' try bloc de code.

Voici un autre exemple qui auront le même comportement indésirable:

except BaseException as e: # don't just do a bare except!
    logging.info(e)

Au lieu de cela, essayez de seulement attraper l'exception spécifique vous savez que vous êtes la recherche pour. Par exemple, si vous savez que vous risquez d'obtenir une valeur d'erreur lors de la conversion:

try:
    foo = operation_that_includes_int(foo)
except ValueError as e:
    if fatal_condition(): # You can raise the exception if it's bad,
        logging.info(e)   # but if it's fatal every time,
        raise             # you probably should just not catch it.
    else:                 # Only catch exceptions you are prepared to handle.
        foo = 0           # Here we simply assign foo to 0 and continue. 

Plus d'Explications avec un autre exemple

Vous pourriez être faire parce que vous avez été le web raclage et l'été se dire, UnicodeError, mais parce que vous avez utilisé le plus large à l'Exception de la capture, de votre code, ce qui peut avoir d'autres défauts fondamentaux, tentera d'exécuter jusqu'à la fin, gaspiller de la bande passante, temps de traitement, à l'usure et à la déchirure sur vos équipements, à court de mémoire, de la collecte des ordures de données, etc.

Si d'autres personnes vous demandant de remplir de sorte qu'ils peuvent compter sur votre code, je comprends se sent obligé de juste occupons de tout. Mais si vous êtes prêt à échouer bruyamment comme vous développer, vous aurez l'occasion de corriger les problèmes qui pourraient n'apparaît que par intermittence, mais ce serait long terme coûteux de bugs.

Avec plus précis de la gestion des erreurs, vous code peut être plus robuste.

27voto

Tupteq Points 755

Vous devez utiliser au moins except Exception: pour éviter d'attraper le système des exceptions comme SystemExit ou KeyboardInterrupt. Voici le lien pour docs.

En général, vous devez définir explicitement les exceptions que vous voulez prendre, pour éviter d'attraper indésirables des exceptions. Vous devez savoir ce que les exceptions de vous ignorer.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X