Diferencia entre excepto: y excepto Excepción como e: en Python

140

Los siguientes fragmentos de código hacen lo mismo. Capturan cada excepción y ejecutan el código en el except:bloque

Fragmento 1 -

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

Fragmento 2 -

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

¿Cuál es exactamente la diferencia en ambas construcciones?

narendranathjoshi
fuente
77
@ user2725093 esa no es la misma pregunta. El que vinculaste pregunta cuál es la diferencia entre except Exception, e:y except Exception as e:. Esta pregunta pregunta cuál es la diferencia entre except:y except Exception as e:.
Dennis

Respuestas:

155

En el segundo puede acceder a los atributos del objeto de excepción:

>>> 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",)

Pero no detecta BaseExceptionni las excepciones que salen del sistema SystemExit, KeyboardInterrupty 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

Que un desnudo, excepto:

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

Consulte la sección Excepciones incorporadas de los documentos y la sección Errores y excepciones del tutorial para obtener más información.

agf
fuente
22
Bueno, no hay magia aquí. Exceptionse deriva de BaseException, por eso except Exceptionno atrapa BaseException. Si escribes except BaseException, también será atrapado. Desnudo exceptsimplemente atrapa todo.
fjarri
2
Debo señalar que un desnudo exceptdebe ser el último en una serie de exceptbloques, mientras que no obtendrá un error si lo coloca except Exceptionantes de otros exceptbloques: simplemente se ignorarán en silencio (si manejan Exceptionsubclases). Algo a tener en cuenta.
Vanessa Phipps
@MatthewPhipps Ese es el punto, ¿no? como declaraciones de casos o bloques if-else, la ejecución salta a la primera condición que coincida ...
Básico
1
@Basic Solo señala otra diferencia entre desnudo excepty except Exception. "Algo a tener en cuenta" parece un poco extraño ahora, pero en ese momento esperaba que Python eligiera el exceptbloque más específico , independientemente de dónde estuviera, y me decepcionó un poco descubrir lo contrario.
Vanessa Phipps
También vale la pena señalar que la segunda forma solo debe usarse si no le importa cuál fue la excepción o si desea manejarla de manera significativa.
Josh J
51
except:

acepta todas las excepciones, mientras que

except Exception as e:

sólo acepta excepciones que estás significaba para la captura.

Aquí hay un ejemplo de uno que no debes atrapar:

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

El primero silenció el KeyboardInterrupt!

Aquí hay una lista rápida:

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 quieres atrapar alguno de ellos, es mejor hacerlo

except BaseException:

para señalar que sabes lo que estás haciendo.


Todas las excepciones provienen BaseException, y aquellas de las que debes atrapar día a día (las que se lanzarán para el programador) también heredan Exception.

Veedrac
fuente
except(Exception)nunca atrapa KeyboardInterrupterrores. as eno tiene nada que ver con eso.
pandita
2
Nunca dije que así fuera. No he mencionado ni una sola vez as e, porque supuse que es obvio lo que hace.
Veedrac
2
¿Hay algún caso en el que una persona atrape BaseException Y sepa lo que está haciendo?
Davos
2
@Davos Sí, es posible que lo prefieras al hacer un registro transitorio, o si le ofreces una consola al usuario de la que no quieres excepciones SystemExito de las KeyboardInterruptque escapar. No es un caso común, pero sucede.
Veedrac
14

Existen diferencias con algunas excepciones, por ejemplo, KeyboardInterrupt.

Lectura PEP8 :

Una cláusula excepto: capturará excepciones de SystemExit y KeyboardInterrupt, lo que dificultará la interrupción de un programa con Control-C, y puede ocultar otros problemas. Si desea detectar todas las excepciones que señalan errores del programa, use excepto Exception: (desnudo excepto es equivalente a excepto BaseException :).

Diego Herranz
fuente
3

El uso del segundo formulario le proporciona una variable (nombrada en función de la ascláusula, en su ejemplo e) en el exceptámbito del bloque con el objeto de excepción vinculado a él para que pueda usar la información en la excepción (tipo, mensaje, seguimiento de pila, etc.) para manejar la excepción en una mansión más especialmente adaptada.

Rayo Silas
fuente
1

Otra forma de ver esto. Consulte los detalles de la excepción:

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']

Hay muchas "cosas" para acceder usando la sintaxis 'como e'.

Este código estaba destinado únicamente a mostrar los detalles de esta instancia.

jouell
fuente