¿Es mejor "probar" algo y detectar la excepción o probar si es posible primero evitar una excepción?

Resuelto chown asked hace 12 años • 8 respuestas

¿Debo probar ifque algo es válido o simplemente tryhacerlo y detectar la excepción?

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

Por ejemplo, ¿debería:

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

O:

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

Algunas reflexiones...
PEP 20 dice:

Los errores nunca deben pasar en silencio.
A menos que se silencie explícitamente.

¿Debería interpretarse el uso de a tryen lugar de an como un error que se transmite en silencio? ifY si es así, ¿lo está silenciando explícitamente al usarlo de esta manera y, por lo tanto, está bien?


No me refiero a situaciones en las que sólo puedes hacer las cosas de una manera; Por ejemplo:

try:
    import foo
except ImportError:
    import baz
chown avatar Sep 30 '11 06:09 chown
Aceptado

Deberías preferirlo try/exceptsi if/elseeso resulta en

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

A menudo, estos van de la mano.


aceleraciones

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

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

intentarlo, excepto es la mejor opción cuando indexprobablemente esté en la lista y el IndexError generalmente no se genera. De esta manera evitará la necesidad de realizar una búsqueda adicional mediante if index < len(my_list).

Python fomenta el uso de excepciones, que manejas es una frase de Dive Into Python . Su ejemplo no solo maneja la excepción (elegantemente), en lugar de dejarla pasar silenciosamente , sino que 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 más limpio

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 resultar en un código más limpio y más 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(s)

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

try:
    return int(s)
except (TypeError, ValueError, OverflowError): #int conversion failed
    return None
Remi avatar Sep 30 '2011 00:09 Remi

En este caso particular, deberías usar algo completamente diferente:

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

Sin embargo, en general: si espera que la prueba falle con frecuencia, utilice if. Si la prueba es costosa en comparación con simplemente intentar la operación y detectar la excepción si falla, use try. Si ninguna de estas condiciones se aplica, elija la que le resulte más fácil.

 avatar Sep 29 '2011 23:09

Siempre se debe usar tryy exceptdirectamente en lugar de dentro de una ifprotección si existe alguna posibilidad de una condición de carrera. Por ejemplo, si desea asegurarse de que exista 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 isdiry mkdir, saldrás. En su lugar, 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'.

John Cowan avatar Sep 22 '2015 20:09 John Cowan

Si es trivial comprobar si algo fallará antes de hacerlo, probablemente debería favorecerlo. Después de todo, crear excepciones (incluidos sus rastreos asociados) lleva tiempo.

Se deben utilizar excepciones para:

  1. cosas que son inesperadas, o...
  2. cosas en las que necesitas saltar más de un nivel de lógica (por ejemplo, donde a breakno te lleva lo suficientemente lejos), o...
  3. cosas en las que no sabes exactamente qué va a manejar la excepción de antemano, o...
  4. cosas en las que comprobar con antelación si hay fallos es caro (en comparación con simplemente intentar la operación)

Tenga en cuenta que, a menudo, la respuesta real es "ninguna"; 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')
Amber avatar Sep 29 '2011 23:09 Amber