Différence entre except: et except Exception as e: in Python

140

Les deux extraits de code suivants font la même chose. Ils interceptent chaque exception et exécutent le code dans le except:bloc

Extrait 1 -

try:
    #some code that may throw an exception
except:
    #exception handling code

Extrait 2 -

try:
    #some code that may throw an exception
except Exception as e:
    #exception handling code

Quelle est exactement la différence entre les deux constructions?

narendranathjoshi
la source
7
@ user2725093 ce n'est pas la même question. Celui auquel vous vous êtes lié demande quelle est la différence entre except Exception, e:et except Exception as e:. Cette question demande quelle est la différence entre except:et except Exception as e:.
Dennis

Réponses:

155

Dans le second, vous pouvez accéder aux attributs de l'objet d'exception:

>>> def catch():
...     try:
...         asd()
...     except Exception as e:
...         print e.message, e.args
... 
>>> catch()
global name 'asd' is not defined ("global name 'asd' is not defined",)

Mais il n'attrape BaseExceptionni les exceptions qui sortent du système SystemExit, KeyboardInterruptet GeneratorExit:

>>> def catch():
...     try:
...         raise BaseException()
...     except Exception as e:
...         print e.message, e.args
... 
>>> catch()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 3, in catch
BaseException

Ce qui est nu sauf:

>>> def catch():
...     try:
...         raise BaseException()
...     except:
...         pass
... 
>>> catch()
>>> 

Consultez la section Exceptions intégrées de la documentation et la section Erreurs et exceptions du didacticiel pour plus d'informations.

agf
la source
22
Eh bien, il n'y a pas de magie ici. Exceptionest dérivé de BaseException, c'est pourquoi except Exceptionne pas attraper BaseException. Si vous écrivez except BaseException, il sera capturé aussi. Bare exceptattrape tout.
fjarri le
2
Je dois souligner qu'un bare exceptdoit être le dernier d'une série de exceptblocs, alors que vous n'obtiendrez pas d'erreur si vous mettez except Exceptionavant d'autres exceptblocs: ils seront simplement ignorés en silence (s'ils gèrent des Exceptionsous-classes). Quelque chose à surveiller.
Vanessa Phipps
@MatthewPhipps C'est un peu le problème, n'est-ce pas? comme les instructions case ou les blocs if-else, l'exécution saute à la première condition qui correspond à ...
Basic
1
@Basic Soulignant simplement une autre différence entre bare exceptet except Exception. "Quelque chose à surveiller" semble un peu bizarre maintenant, mais à l'époque je m'attendais à ce que Python choisisse le exceptbloc le plus spécifique , peu importe où il se trouvait, et j'ai été un peu déçu de découvrir le contraire.
Vanessa Phipps
Il est également intéressant de noter que le second formulaire ne doit être utilisé que si vous ne vous souciez pas de la nature de l'exception ou si vous souhaitez la gérer de manière significative.
Josh J
51
except:

accepte toutes les exceptions, alors que

except Exception as e:

n'accepte que les exceptions que vous êtes censé attraper.

Voici un exemple que vous n'êtes pas censé attraper:

>>> try:
...     input()
... except:
...     pass
... 
>>> try:
...     input()
... except Exception as e:
...     pass
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyboardInterrupt

Le premier a fait taire le KeyboardInterrupt!

Voici une liste rapide:

issubclass(BaseException, BaseException)
#>>> True
issubclass(BaseException, Exception)
#>>> False


issubclass(KeyboardInterrupt, BaseException)
#>>> True
issubclass(KeyboardInterrupt, Exception)
#>>> False


issubclass(SystemExit, BaseException)
#>>> True
issubclass(SystemExit, Exception)
#>>> False

Si vous voulez en attraper un, il vaut mieux le faire

except BaseException:

pour souligner que vous savez ce que vous faites.


Toutes les exceptions proviennent de BaseException, et celles que vous êtes censé attraper au jour le jour (celles qui seront lancées pour le programmeur) héritent également de Exception.

Veedrac
la source
except(Exception)ne détecte jamais d' KeyboardInterrupterreurs. as en'a rien à voir avec ça.
pandita
2
Je n'ai jamais dit que c'était le cas. Je n'ai pas mentionné une seule fois le as e, car j'ai supposé que ce qu'il faisait était évident.
Veedrac
2
Y a-t-il un cas où une personne attraperait BaseException ET saurait ce qu'elle fait?
Davos
2
@Davos Ouais, vous pourriez le préférer lors de la journalisation transitoire, ou si vous offrez une console à l'utilisateur que vous ne voulez pas d'exceptions SystemExitou dont vous ne voulez pas KeyboardInterruptéchapper. Ce n'est pas un cas courant, mais cela arrive.
Veedrac
14

Il existe des différences à quelques exceptions près, par exemple KeyboardInterrupt.

Lecture de PEP8 :

Une clause except: nue interceptera les exceptions SystemExit et KeyboardInterrupt, rendant plus difficile l'interruption d'un programme avec Control-C, et peut masquer d'autres problèmes. Si vous voulez attraper toutes les exceptions qui signalent des erreurs de programme, utilisez except Exception: (bare except équivaut à except BaseException :).

Diego Herranz
la source
3

L'utilisation du deuxième formulaire vous donne une variable (nommée en fonction de la asclause, dans votre exemple e) dans la exceptportée du bloc avec l'objet d'exception qui lui est lié afin que vous puissiez utiliser les informations de l'exception (type, message, trace de pile, etc.) pour gérer l'exception dans un manoir plus spécialement conçu.

Silas Ray
la source
1

Une autre façon de voir cela. Consultez les détails de l'exception:

In [49]: try: 
    ...:     open('file.DNE.txt') 
    ...: except Exception as  e: 
    ...:     print(dir(e)) 
    ...:                                                                                                                                    
['__cause__', '__class__', '__context__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__suppress_context__', '__traceback__', 'args', 'characters_written', 'errno', 'filename', 'filename2', 'strerror', 'with_traceback']

Il y a beaucoup de "choses" auxquelles accéder en utilisant la syntaxe 'as e'.

Ce code était uniquement destiné à afficher les détails de cette instance.

jouell
la source