versiones guia español descargar actualizar python exception-handling if-statement try-catch pep

python - guia - qgis manual



¿Es mejor ''probar'' algo y atrapar la excepción o probar si es posible primero evitar una excepción? (7)

¿Debería probar if algo es válido o simplemente try de hacerlo y atrapar la excepción?

  • ¿Existe alguna documentación sólida que indique que se prefiere una forma?
  • ¿Es de alguna manera más pitónico ?

Por ejemplo, debería yo:

if len(my_list) >= 4: x = my_list[3] else: x = ''NO_ABC''

O:

try: x = my_list[3] except IndexError: x = ''NO_ABC''

Algunos pensamientos...
PEP 20 dice:

Los errores nunca deberían pasar silenciosamente.
A menos que esté explícitamente silenciado.

¿Debería usar una try lugar de una if se interpreta como un error que pasa silenciosamente? Y si es así, ¿lo silencian explícitamente al usarlo de esta manera, por lo tanto, lo hace correcto?

No me refiero a situaciones en las que solo puedes hacer las cosas de 1 manera; por ejemplo:

try: import foo except ImportError: import baz


¿Debería usar una prueba en lugar de una si se interpreta como un error que pasa silenciosamente? Y si es así, ¿lo silencian explícitamente al usarlo de esta manera, por lo tanto, lo hace correcto?

Usar try es reconocer que puede pasar un error, que es lo opuesto a que pase silenciosamente. El uso de except hace que no pase en absoluto.

Usando try: except: es preferido en casos donde if: else: logic es más complicado. Simple es mejor que complejo; Complejo es mejor que complicado; y es más fácil pedir perdón que permiso.

Lo que "los errores nunca deben pasar silenciosamente" es una advertencia, es el caso en que el código podría generar una excepción que usted conozca, y en la que su diseño admite la posibilidad, pero no ha diseñado de manera que pueda lidiar con la excepción. Silenciar explícitamente un error, desde mi punto de vista, sería hacer algo como pass en un bloque except , lo cual solo debería hacerse con la comprensión de que "no hacer nada" realmente es el correcto manejo de errores en una situación particular. (Esta es una de las pocas veces en las que creo que realmente es necesario un comentario en un código bien escrito).

Sin embargo, en su ejemplo particular, ninguno es apropiado:

x = myDict.get(''ABC'', ''NO_ABC'')

La razón por la que todos señalan esto, aunque reconozcas tu deseo de comprender en general, y la incapacidad de encontrar un mejor ejemplo, es que en realidad existen pasos laterales equivalentes en muchos casos, y buscarlos es primer paso para resolver el problema


Como los otros mensajes mencionan, depende de la situación. Existen algunos peligros con el uso de try / except en lugar de verificar la validez de sus datos por adelantado, especialmente cuando se usa en proyectos más grandes.

  • El código en el bloque try puede tener la posibilidad de causar todo tipo de estragos antes de que se capture la excepción: si compruebas proactivamente de antemano con un enunciado if, puedes evitarlo.
  • Si el código invocado en su bloque try genera un tipo de excepción común, como TypeError o ValueError, es posible que no capte la misma excepción que esperaba captar. Puede ser otra cosa que plantee la misma clase de excepción antes o después de llegar a la línea donde su excepción puede ser levantada.

por ejemplo, supongamos que tiene:

try: x = my_list[index_list[3]] except IndexError: x = ''NO_ABC''

IndexError no dice nada sobre si ocurrió al intentar obtener un elemento de index_list o my_list.


Deberías preferir try/except over if/else si eso resulta en

  • aceleraciones (por ejemplo, evitando búsquedas adicionales)
  • código limpiador (menos líneas / más fácil de leer)

A menudo, estos van de la mano.

aceleraciones

En el caso de tratar de encontrar un elemento en una lista larga:

try: x = my_list[index] except IndexError: x = ''NO_ABC''

el intento, excepto que es la mejor opción cuando el index está probablemente en la lista y el IndexError generalmente no se plantea. De esta forma, evita la necesidad de una búsqueda adicional if index < len(mylist) .

Python fomenta el uso de excepciones, que usted maneja es una frase de Dive Into Python . Su ejemplo no solo maneja la excepción (con gracia), en lugar de dejar que pase silenciosamente , también la excepción ocurre solo en el caso excepcional de que no se encuentre el índice (¡de ahí la palabra excepción !).

código limpiador

La documentación oficial de Python menciona EAFP : es más fácil pedir perdón que permiso y Rob Knight señala que detectar errores en lugar de evitarlos puede dar como resultado un código más limpio y fácil de leer. Su ejemplo lo dice así:

Peor (LBYL ''mira antes de saltar) :

#check whether int conversion will raise an error if not isinstance(s, str) or not s.isdigit: return None elif len(s) > 10: #too many digits for int conversion return None else: return int(str)

Mejor (EAFP: es más fácil pedir perdón que permiso) :

try: return int(str) except (TypeError, ValueError, OverflowError): #int conversion failed return None


En este caso particular, debe usar algo completamente diferente:

x = myDict.get("ABC", "NO_ABC")

En general, sin embargo: si espera que la prueba falle con frecuencia, use if . Si la prueba es costosa en comparación con solo probar la operación y atrapar la excepción si falla, use try . Si ninguna de estas condiciones se aplica, haga lo que sea más fácil leer.


Para un significado general, puede considerar leer Modismos y Anti-Modismos en Python: Excepciones .

En su caso particular, como han dicho otros, debe usar dict.get() :

get (clave [, predeterminado])

Devuelve el valor de la clave si la clave está en el diccionario, de lo contrario, será el valor predeterminado. Si no se proporciona el valor predeterminado, su valor predeterminado es Ninguno, por lo que este método nunca genera un KeyError.


Si es trivial verificar si algo va a fallar antes de hacerlo, probablemente deberías favorecerlo. Después de todo, la construcción de excepciones (incluidos los registros de seguimiento asociados) lleva tiempo.

Las excepciones se deben usar para:

  1. cosas que son inesperadas, o ...
  2. cosas donde necesitas saltar más de un nivel de lógica (por ejemplo, donde un break no te lleva lo suficientemente lejos), o ...
  3. cosas donde no se sabe exactamente qué va a manejar la excepción antes de tiempo, o ...
  4. cosas donde verificar con anticipación la falla es costoso (en relación a solo intentar la operación)

Tenga en cuenta que a menudo, la respuesta real es "ninguno"; por ejemplo, en su primer ejemplo, lo que realmente debe hacer es usar .get() para proporcionar un valor predeterminado:

x = myDict.get(''ABC'', ''NO_ABC'')


Usar try y except directamente en lugar de dentro y if siempre se debe hacer un guardia si hay alguna posibilidad de una condición de carrera. Por ejemplo, si quiere asegurarse de que existe un directorio, no haga esto:

import os, sys if not os.path.isdir(''foo''): try: os.mkdir(''foo'') except OSError, e print e sys.exit(1)

Si otro hilo o proceso crea el directorio entre isdir y mkdir , saldrá. En cambio, haz esto:

import os, sys, errno try: os.mkdir(''foo'') except OSError, e if e.errno != errno.EEXIST: print e sys.exit(1)

Eso solo saldrá si no se puede crear el directorio ''foo''.