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

3258

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 se me ocurre ahora mismo es hacer esto:

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

¿Hay alguna forma 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 bien, 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 detectar las dos excepciones distintas no se concreta exactamente.

¿Hay alguna forma de hacer esto?

1
  • 18
    Tenga en cuenta que en Python 3, esta última ya no es una sintaxis válida. gerrit 17/04/19 a las 14:01
4396

De la documentación de Python :

An except clause may name multiple exceptions as a parenthesized tuple, for example

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á obsoleto y no funciona en Python 3; ahora deberías estar usando as.

9
  • 1
    ¿Es posible almacenar las excepciones deseadas en un iterable y luego capturar el iterable? Estoy tratando de convertir una lista de advertencias en errores usando warnings.filterwarnings, y no quiero tener que especificar la lista de advertencias dos veces. BallpointBen 22 de marzo de 2018 a las 3:04
  • 18
    Lo intenté ... con a list, y resultó en a TypeError. Parece que los errores deben estar en a tuplepara que la captura funcione como se esperaba. BallpointBen 22/03/18 a las 16:02
  • 11
    No estaba claro si la "tupla entre paréntesis" era meramente sintáctica o si se necesitaba una tupla auténtica. "Entre 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 22/03/18 a las 16:48
  • 8
    @JosephBani, ¿qué pasa con las expresiones generadoras? jammertheprogrammer 12/04/19 a las 0:09
  • 31
    @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 12/07/19 a las 20:25
382

How do I catch multiple exceptions in one line (except block)

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 la sintaxis anterior que usaba las comas para asignar el objeto de error a un nombre. La aspalabra clave se utiliza para la tarea. Puede usar cualquier nombre para el objeto de error, yo prefiero errorpersonalmente.

Mejores prácticas

Para hacer esto de una manera actual y compatible con Python, debe separar las Excepciones con comas y envolverlas entre paréntesis para diferenciarlas de la sintaxis anterior que asignó la instancia de excepción a un nombre de variable siguiendo el tipo de excepción para ser capturado con un coma.

A continuación, se muestra un ejemplo de uso simple:

import sys

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

Estoy especificando solo estas excepciones para evitar ocultar errores, de los cuales, si encuentro, espero el seguimiento de la pila completa.

Esto está documentado aquí: https://docs.python.org/tutorial/errors.html

Puede asignar la excepción a una variable ( ees común, pero es posible que prefiera 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á obsoleto, y si desea que su código sea compatible con versiones posteriores en 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 quiera passen ciertas excepciones, use suppress.

1
  • 13
    Buena adición de suppress, mucho más legible que simplemente hacer passenexceptMache 17 dic 2019 a las 9:14
58

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

A try statement may have more than one except clause, to specify handlers for different exceptions. At most one handler will be executed. Handlers only handle exceptions that occur in the corresponding try clause, not in other handlers of the same try statement. An except clause may name multiple exceptions as a parenthesized tuple, for example:

except (RuntimeError, TypeError, NameError):
    pass

Note that the parentheses around this tuple are required, because except ValueError, e: was the syntax used for what is normally written as except ValueError as e: in modern Python (described below). The old syntax is still supported for backwards compatibility. This means except RuntimeError, TypeError is not equivalent to except (RuntimeError, TypeError): but to except RuntimeError as TypeError: which is not what you want.

0
45

Si utiliza con frecuencia una gran cantidad de excepciones, puede predefinir una tupla, de modo que no tenga 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 además de las de la tupla predefinida, deberá definir otro bloque excepto.

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

23

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 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 la segunda no es la mejor manera de hacer esto, pero solo estoy mostrando varias formas de hacerlo.

2
  • 1
    Estoy usando el segundo porque tengo dos excepciones diferentes y cada una debe procesarse de manera diferente. ¿Hay algo de malo en hacerlo de esa manera? chizou 2 de julio de 2019 a las 3:11
  • 2
    @majikman El segundo método con múltiples cláusulas, cada una de las cuales llama a la misma función, no es el mejor cuando intentas no repetirte y hacer 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 13/08/19 a las 19:29