python ejemplos - Capturar múltiples excepciones en una línea(excepto el bloque)




pass module (7)

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 ahora 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

Por lo tanto, mi esfuerzo por atrapar las dos excepciones distintas no se concreta.

¿Hay alguna forma de hacer esto?


Answers

De la documentación de Python -> 8.3 Manejo de excepciones :

Una declaración de try puede tener más de una cláusula de excepción, para especificar manejadores para diferentes excepciones. A lo sumo se ejecutará un controlador. Los manejadores solo manejan las excepciones que ocurren en la cláusula try correspondiente, no en otros manejadores de la misma declaración try. Una cláusula de excepción 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: fue la sintaxis utilizada para lo que normalmente se escribe como except ValueError as e: en Python moderno (descrito a continuación). La sintaxis antigua todavía es compatible con la compatibilidad con versiones anteriores. Esto significa que except RuntimeError, TypeError no es equivalente a except (RuntimeError, TypeError): pero a except RuntimeError as TypeError: que no es lo que desea.


Si utiliza con frecuencia un gran número 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 bloque excepto.

  2. Si no puede tolerar una variable global, defínala en main () y pásela cuando sea necesario ...


¿Cómo detecto 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 necesarios debido a una sintaxis más antigua que usaba las comas para asignar el objeto de error a un nombre. La palabra clave as se utiliza para la asignación. Puede usar cualquier nombre para el objeto de error, prefiero el error personalmente.

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 para capturar con coma.

Aquí hay un ejemplo de uso simple:

try:
    mainstuff()
except (KeyboardInterrupt, EOFError): # the parens are necessary
    quit(0)

Especifico solo estas excepciones para evitar que se oculten los errores, los cuales, 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, ( e es común, pero puede preferir una variable más detallada si tiene un manejo prolongado de excepciones o su IDE solo resalta las selecciones más grandes, como la mía). La instancia tiene un atributo args. Aquí hay un ejemplo:

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

Tenga en cuenta que en Python 3, el objeto err cae fuera del alcance cuando se concluye el bloque de except .

Obsoleto

Puede ver el 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 reenvío en Python 3, debe actualizar la sintaxis para usar el nuevo formulario:

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

Si ve la asignación del nombre de la 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 realice la actualización.

El administrador de contexto de suppress

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

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

El try , except líneas de pass , se puede manejar en una sola línea con el administrador de contexto de supresión, disponible en Python 3.4 :

from contextlib import suppress

with suppress(IDontLikeYouException, YouAreBeingMeanException):
     do_something()

Así que cuando quiera pass ciertas excepciones, utilice suppress .


Una de las maneras de hacer esto 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 ejecute la tarea ejecutada por except bloquear y llamarla a través de todo el bloque de except 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 la segunda no es la mejor manera de hacer esto, pero solo estoy mostrando varias formas de hacer esto.


La documentación de Python 2.7 establece que:

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

try:
    raise ValueError("hello")
except (RuntimeError, ValueError, KeyError) as a:
    print a

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


De la documentación de Python :

Una cláusula de excepción 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 usar as .


Con las excepciones de Python modernas, no necesita abusar de .message , o invalidar .__str__() o .__repr__() o cualquiera de ellas. Si todo lo que desea es un mensaje informativo cuando se produce la excepción, haga lo siguiente:

class MyException(Exception):
    pass

raise MyException("My hovercraft is full of eels")

Eso dará una respuesta que terminará con MyException: My hovercraft is full of eels .

Si desea más flexibilidad de la excepción, puede pasar un diccionario como argumento:

raise MyException({"message":"My hovercraft is full of animals", "animal":"eels"})

Sin embargo, llegar a esos detalles en un bloque de except es un poco más complicado. Los detalles se almacenan en el atributo args , que es una lista. Necesitarías hacer algo como esto:

try:
    raise MyException({"message":"My hovercraft is full of animals", "animal":"eels"})
except MyException as e:
    details = e.args[0]
    print(details["animal"])

Todavía es posible pasar varios elementos a la excepción y acceder a ellos a través de índices de tuplas, pero esto es muy desalentador (e incluso fue destinado a la desaprobación hace un tiempo). Si necesita más que una sola pieza de información y el método anterior no es suficiente para usted, entonces debe subclase Exception como se describe en el tutorial .

class MyError(Exception):
    def __init__(self, message, animal):
        self.message = message
        self.animal = animal
    def __str__(self):
        return self.message




python exception exception-handling