Captura múltiples excepciones en una línea (excepto el bloque)

2759

Sé que puedo hacer:

try:
    # do something that may fail
except:
    # do this if ANYTHING goes wrong

También puedo hacer esto:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreTooShortException:
    # stand on a ladder

Pero si quiero hacer lo mismo dentro de dos excepciones diferentes, lo mejor que puedo pensar en este momento es hacer esto:

try:
    # do something that may fail
except IDontLikeYouException:
    # say please
except YouAreBeingMeanException:
    # say please

¿Hay alguna manera de que pueda hacer algo como esto (ya que la acción a tomar en ambas excepciones es say please):

try:
    # do something that may fail
except IDontLikeYouException, YouAreBeingMeanException:
    # say please

Ahora esto realmente no funcionará, ya que coincide con la sintaxis de:

try:
    # do something that may fail
except Exception, e:
    # say please

Entonces, mi esfuerzo por atrapar las dos excepciones distintas no se concreta exactamente.

¿Hay alguna forma de hacer esto?

inspectorG4dget
fuente
66
Tenga en cuenta que en Python 3, este último ya no es una sintaxis válida.
gerrit

Respuestas:

3727

De la documentación de Python :

Una cláusula except puede nombrar múltiples excepciones como una tupla entre paréntesis, por ejemplo

except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

O, solo para Python 2:

except (IDontLikeYouException, YouAreBeingMeanException), e:
    pass

Separar la excepción de la variable con una coma seguirá funcionando en Python 2.6 y 2.7, pero ahora está en desuso y no funciona en Python 3; ahora deberías estar usando as.

carne_mecánica
fuente
99
Lo intenté ... con un list, y resultó en un TypeError. Parece que los errores deben estar en una tuplepara que la captura funcione como se esperaba.
BallpointBen
44
¿Por qué habría utilizado alguna vez una lista cuando ve claramente que está documentado que se necesita una tupla en este caso?
mechanical_meat
66
No estaba claro si la "tupla entre paréntesis" era meramente sintáctica o si se requería una tupla de buena fe. "Paréntesis" es engañoso porque puede crear una tupla sin paréntesis en otro lugar y luego usarla en la exceptlínea. Solo está necesariamente entre paréntesis si se crea en la exceptlínea.
BallpointBen
55
@JosephBani, ¿qué pasa con las expresiones generadoras?
jammertheprogrammer
12
@JosephBani Eso no es cierto en absoluto. En 2 + (x * 2), (x * 2)ciertamente no es una tupla. Los paréntesis son una construcción de agrupación general. La característica definitoria de una tupla es que contiene una coma . Consulte la documentación de Python : "Tenga en cuenta que en realidad es la coma la que hace una tupla, no los paréntesis".
Soren Bjornstad
314

¿Cómo atrapo varias excepciones en una línea (excepto el bloque)

Hacer esto:

try:
    may_raise_specific_errors():
except (SpecificErrorOne, SpecificErrorTwo) as error:
    handle(error) # might log or have some other default behavior...

Los paréntesis son obligatorios debido a una sintaxis anterior que utilizaba las comas para asignar el objeto de error a un nombre. La aspalabra clave se usa para la asignación. Puede usar cualquier nombre para el objeto de error, prefiero errorpersonalmente.

Mejores prácticas

Para hacer esto de una manera actual y compatible con Python, debe separar las Excepciones con comas y envolverlas con paréntesis para diferenciar de la sintaxis anterior que asignó la instancia de excepción a un nombre de variable siguiendo el Tipo de excepción que se capturará con un coma.

Aquí hay un ejemplo de uso simple:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError): # the parens are necessary
    sys.exit(0)

Solo especifico estas excepciones para evitar esconder errores, que si encuentro espero el seguimiento completo de la pila.

Esto se documenta aquí: https://docs.python.org/tutorial/errors.html

Puede asignar la excepción a una variable, ( ees común, pero puede preferir una variable más detallada si tiene un manejo de excepciones prolongado o su IDE solo resalta selecciones más grandes que eso, como lo hace el mío). La instancia tiene un atributo args. Aquí hay un ejemplo:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError) as err: 
    print(err)
    print(err.args)
    sys.exit(0)

Tenga en cuenta que en Python 3, el errobjeto queda fuera de alcance cuando exceptse concluye el bloque.

Obsoleto

Es posible que vea un código que asigna el error con una coma. Este uso, el único formulario disponible en Python 2.5 y versiones anteriores, está en desuso, y si desea que su código sea compatible con Python 3, debe actualizar la sintaxis para usar el nuevo formulario:

import sys

try:
    mainstuff()
except (KeyboardInterrupt, EOFError), err: # don't do this in Python 2.6+
    print err
    print err.args
    sys.exit(0)

Si ve la asignación de nombre de coma en su base de código, y está usando Python 2.5 o superior, cambie a la nueva forma de hacerlo para que su código siga siendo compatible cuando actualice.

El suppressadministrador de contexto

La respuesta aceptada es realmente 4 líneas de código, mínimo:

try:
    do_something()
except (IDontLikeYouException, YouAreBeingMeanException) as e:
    pass

El try, except, passlíneas pueden ser manejados en una sola línea con el gestor de contexto suprimir, disponible en Python 3.4 :

from contextlib import suppress

with suppress(IDontLikeYouException, YouAreBeingMeanException):
     do_something()

Entonces, cuando desee passciertas excepciones, use suppress.

Aaron Hall
fuente
2
Además de la buena suppress, mucho más legible que acaba de hacer passenexcept
Mache
50

De la documentación de Python -> 8.3 Excepciones de manejo :

Una trydeclaración puede tener más de una cláusula, excepto, para especificar controladores para diferentes excepciones. Como máximo se ejecutará un controlador. Los manejadores solo manejan excepciones que ocurren en la cláusula try correspondiente, no en otros manejadores de la misma declaración try. Una cláusula except puede nombrar múltiples excepciones como una tupla entre paréntesis, por ejemplo:

except (RuntimeError, TypeError, NameError):
    pass

Tenga en cuenta que los paréntesis alrededor de esta tupla son obligatorios, porque excepto ValueError, e:la sintaxis utilizada para lo que normalmente se escribe como except ValueError as e:en Python moderno (descrito a continuación). La sintaxis anterior aún es compatible para la compatibilidad con versiones anteriores. Esto significa except RuntimeError, TypeErrorque no es equivalente except (RuntimeError, TypeError):a lo except RuntimeError as TypeError:que no es lo que quieres.

fedorqui 'así que deja de dañar'
fuente
35

Si utiliza con frecuencia una gran cantidad de excepciones, puede predefinir una tupla, por lo que no tiene que volver a escribirlas muchas veces.

#This example code is a technique I use in a library that connects with websites to gather data

ConnectErrs  = (URLError, SSLError, SocketTimeoutError, BadStatusLine, ConnectionResetError)

def connect(url, data):
    #do connection and return some data
    return(received_data)

def some_function(var_a, var_b, ...):
    try: o = connect(url, data)
    except ConnectErrs as e:
        #do the recovery stuff
    blah #do normal stuff you would do if no exception occurred

NOTAS

  1. Si también necesita capturar otras excepciones que las de la tupla predefinida, deberá definir otro excepto el bloque.

  2. Si no puede tolerar una variable global, defínalo en main () y páselo donde sea necesario ...

barba blanca
fuente
17

Una de las formas de hacerlo es ...

try:
   You do your operations here;
   ......................
except(Exception1[, Exception2[,...ExceptionN]]]):
   If there is any exception from the given exception list, 
   then execute this block.
   ......................
else:
   If there is no exception then execute this block. 

y otra forma es crear un método que realice la tarea ejecutada por el exceptbloque y llamarlo a través de todo el exceptbloque que escriba.

try:
   You do your operations here;
   ......................
except Exception1:
    functionname(parameterList)
except Exception2:
    functionname(parameterList)
except Exception3:
    functionname(parameterList)
else:
   If there is no exception then execute this block. 

def functionname( parameters ):
   //your task..
   return [expression]

Sé que el segundo no es la mejor manera de hacer esto, pero solo estoy mostrando varias formas de hacer esto.

M.Usman
fuente
Estoy usando el segundo porque tengo dos excepciones diferentes que cada una necesita ser procesada de manera diferente. ¿Hay algo malo en hacerlo de esa manera?
majikman
@majikman El segundo método con múltiples cláusulas, cada una de las cuales llama a la misma función, no es la mejor cuando intenta no repetirse y hace lo mismo para dos excepciones. (Consulte las otras respuestas para conocer la forma correcta de hacerlo). Sin embargo, tener varias exceptcláusulas es normal cuando desea manejar las excepciones de manera diferente.
Eponymous