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:
-
Ne pas attraper de toute erreur. Toujours spécifier les exceptions que vous êtes prêt à récupérer et des seuls à attraper les.
-
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 NameError
s et SyntaxError
s. 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.