Cómo no manejar excepciones en Python
Veo a muchas personas que manejan las excepciones de manera incorrecta. Tal vez esto se aplica a usted también. ¿Te suena familiar la siguiente situación?
Está escribiendo código, pero sabe que la biblioteca que está utilizando podría generar una excepción. No recuerdas cuál, exactamente. En este punto, es tentador usar los llamados bloques generales y continuar con las cosas divertidas.
Tabla de contenidos
- La peor manera de hacerlo
- Una forma algo mejor de detectar todas las excepciones
- Se pone aún peor
- Atrapa lo que puedes manejar
- Conclusión
La peor manera de hacerlo
Lo peor que puede hacer es crear un bloque de prueba excepto que atrape cualquier cosa. Por catch-all, me refiero a algo como:
try: ... except: pass
Los bloques catch-all como estos son malos porque:
- No tiene idea de qué otras excepciones podrían surgir (más sobre esto más adelante).
- Ocultamos la excepción al usar silenciosamente pasar en lugar de registrar el error.
Además, una excepción vacía captará todo, incluido KeyboardInterrupt
(control + c), SystemExit
, e incluso NameErrors
! Esto significa que el siguiente código no se puede detener limpiamente:
from time import sleep while True: try: print("Try and stop me") sleep(1) except: print("Don't.. stop.. me now!")
Siéntete libre de probarlo. Debe cerrar la ventana de su terminal o eliminar el proceso de Python para detener este programa.
Una forma algo mejor de capturar todas las excepciones
Por el contrario, cuando se usa except Exception
, aunque sigue siendo una forma rápida y sucia de detectar demasiadas excepciones, al menos podrá detener el proceso en ejecución correctamente:
from time import sleep while True: try: print("Try and stop me") sleep(1) except Exception: print("Ok I'll stop!")
Al atrapar Exception
no atraparás SystemExit
, KeyboardInterrupt
y otras excepciones similares. ¿Por qué es eso, preguntas?
Todas las excepciones heredan de una clase llamada BaseException
. Según la documentación oficial:“En un try
declaración con un except
cláusula que menciona una clase en particular, esa cláusula también maneja cualquier clase de excepción derivada de esa clase”. Un except
vacío es equivalente a except BaseException
, por lo tanto, detectará todas las excepciones posibles.
Por el contrario, la clase Exception
se define como:“Todas las excepciones integradas que no salen del sistema se derivan de esta clase. Todas las excepciones definidas por el usuario también deben derivarse de esta clase.”
Se pone aún peor
En el siguiente ejemplo, usamos la biblioteca os para obtener el directorio de trabajo actual. Sin embargo, mis pequeños dedos gordos cometieron un error tipográfico:
import os try: working_dir = os.getcdw() print(working_dir) except: print('error')
Porque os.getcdw
no es una función en el módulo os, se lanza un NameError. En lugar de fallar, la cláusula de excepción detectará el error, imprimirá "error" y el programa continuará a pesar de nuestro flagrante error tipográfico. Desafortunadamente, este no se puede resolver capturando Exception
tampoco!
Aparentemente, nuestro pequeño truco del primer paso no soluciona todos nuestros problemas. Entonces, ¿qué debería hacemos?
Atrapa lo que puedas manejar
Una frase que se escucha a menudo sobre las excepciones es:atrapa lo que puedes manejar . Muchos desarrolladores se sienten tentados a lidiar directamente con las excepciones, mientras que a menudo es mejor dejar que la excepción se propague a una parte de su programa que realmente pueda manejarla.
Por ejemplo, considere la parte de un editor de texto que abre y carga archivos, llamémoslo OpenFile
clase. Si el usuario solicitó abrir un archivo que no existe, puede manejar ese error directamente o dejar que se propague.
En este caso, es mejor propagar la excepción a la persona que llama, porque OpenFile
no tiene idea de lo mala que es esta excepción para la persona que llama. La persona que llama puede manejar la situación de varias maneras:
- Podría crear un nuevo archivo con ese nombre y continuar
- Tal vez la persona que llama necesita que el archivo esté allí, en cuyo caso puede mostrar un cuadro de diálogo de error para informar al usuario que este archivo no existe.
De cualquier manera, no está en el OpenFile
clase para decidir qué hacer en caso de un FileNotFoundError
.
Entonces, ¿siempre se debe propagar una excepción? No. Una posible excepción que se puede manejar en la clase FileOpen es el TimeoutError
. Es posible que desee volver a intentarlo varias veces, por ejemplo, sin molestar a la persona que llama con el error. Esta es una excepción que OpenFile
puede manejar, por lo que está bien atraparlo y volver a intentarlo.
Conclusión
Bajo ninguna circunstancia debe capturar más excepciones de las que puede manejar. Los bloques de excepción general son una receta para los errores y el código impredecible. En otras palabras:atrapa lo que puedas manejar.
Si escribe su código con el matra 'captura lo que puede manejar' en mente, escribir bloques comodín está rompiendo todas las reglas. Así que por favor, deja de hacerlo. Como ejercicio, ¡podría revisar parte de su código existente y ver si se puede mejorar con este nuevo conocimiento!
python
- Operadores de Python
- Errores de Python y excepciones integradas
- Excepciones personalizadas de Python
- ¿Cómo obtener la fecha y hora actuales en Python?
- Java captura múltiples excepciones
- Cómo no apestar al enseñar software nuevo
- Declaración Python Print():cómo imprimir con ejemplos
- Apéndice del diccionario de Python:cómo agregar un par clave/valor
- Python New Line:Cómo imprimir SIN Newline en Python
- Promedio de Python:cómo encontrar el PROMEDIO de una lista en Python
- ¿Estás contratando ahora? Cómo manejar una afluencia de solicitantes