¿Cómo detectar múltiples excepciones en una línea? (en el bloque "excepto")
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 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 realizar 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 materializa exactamente.
¿Hay alguna forma de hacer esto?
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 estar usando as
.
¿Cómo puedo detectar múltiples excepciones en una línea (excepto 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 la sintaxis anterior que usaba comas para asignar el objeto de error a un nombre. La as
palabra clave se utiliza para la tarea. Puede utilizar cualquier nombre para el objeto de error, yo error
personalmente lo prefiero.
Mejores prácticas
Para hacer esto de una manera compatible actualmente y en el futuro con Python, debe separar las Excepciones con comas y envolverlas entre paréntesis para diferenciarlas de la sintaxis anterior que asignaba la instancia de excepción a un nombre de variable siguiendo el tipo de excepción que se detectará con un coma.
A continuación se muestra un ejemplo de uso sencillo:
import sys
try:
mainstuff()
except (KeyboardInterrupt, EOFError): # the parens are necessary
sys.exit(0)
Estoy especificando solo estas excepciones para evitar ocultar errores, que si los encuentro espero obtener el seguimiento completo de la pila.
Esto está documentado aquí: https://docs.python.org/tutorial/errors.html
Puede asignar la excepción a una variable ( e
es común, pero es posible que prefiera una variable más detallada si tiene un manejo de excepciones prolongado o si 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 err
objeto queda fuera de alcance cuando except
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 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 del nombre de coma en su código base 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 suppress
administrador de contexto
La respuesta aceptada es en realidad 4 líneas de código, mínimo:
try:
do_something()
except (IDontLikeYouException, YouAreBeingMeanException) as e:
pass
Las líneas try
, except
, pass
se pueden 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()
Entonces, cuando quieras pass
en ciertas excepciones, usa suppress
.
De la documentación de Python -> 8.3 Manejo de excepciones :
Una
try
declaración puede tener más de una cláusula excepto, para especificar controladores para diferentes excepciones. Se ejecutará como máximo un controlador. Los controladores solo manejan excepciones que ocurren en la cláusula try correspondiente, no en otros controladores 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 except
ValueError, e:
era la sintaxis utilizada para lo que normalmente se escribeexcept ValueError as e:
en Python moderno (que se describe a continuación). La sintaxis anterior todavía se admite por compatibilidad con versiones anteriores. Este medioexcept RuntimeError, TypeError
no equivale aexcept (RuntimeError, TypeError):
pero aexcept RuntimeError as
TypeError:
cual no es lo que quieres.
Si utiliza con frecuencia una gran cantidad de excepciones, puede predefinir una tupla, para no tener 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:
Si también necesita detectar otras excepciones además de las de la tupla predefinida, deberá definir otro bloque excepto.
Si simplemente no puede tolerar una variable global, defínala en main() y pásela donde sea necesario...