Excepciones en Python



@eduardo_gpg

Número de visitas 1514

Tiempo de lectura 5 min

10 Junio 2022

En Python, al igual que en muchos otros lenguajes de programación, existe el concepto de Excepción, que, en términos simples, no es más que un error que ocurren en tiempo de ejecución.

Cuando un error se suscita, y el programa no sabe como lidiar con él, es lanzada una excepción, finalizando el programa de forma abrupta. 😣

Los errores pueden ocurrir por múltiples factores, independientemente si tu sintaxis es correcta o no.

Aquí un par de ejemplos de errores:

  • Error de sintaxis.
  • Archivos inexistentes
  • Índices fuera de rango

Los errores son cotidianos, y sin duda alguna tarde o témpanos nos toparemos con ellos en nuestros desarrollos, así que, en lugar de intentar crear programas sin errores, mejor aprendamos a lidiar y convivir con ellos. Recuerda, en Python Los errores no deben pasar desapercibidos. 🐍

Es por ello que, en esta nueva entrega de PyWombat, me gustaría abordáramos el tema de Excepciones. Apedreamos a manejar los errores. y ¿por qué no? a crearlos. 😯

Será un post sumamente interesante, así que te invito a que te quedes. 🤖

Bien, una vez dicho todo esto, y sin más introducción comencemos con esta entrega.

Manejo de errores 🐛

Como mencionamos anteriormente, los errores son algo cotidiano, son cosas que, si bien no podemos evitar, si podemos manejar.

A afortunadamente para nosotros, Python nos ofrece de un mecanismo para lidiar con los errores en tiempo de ejecución, esto mediante los bloques de try y catch.

Veamos un par de ejemplos.

>>> indice = 12
>>> divisores= [0, 1, 2, 3, 4]

>>> lista[indice]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list index out of range

En este caso intento acceder a un índice inexistente para mi objeto lista. Python, al no poder acceder a dicho índice, simplemente lanza la Excepción IndexError.

Para nosotros manejar este posible error haremos uso de un bloque try y un except.

indice = 12
divisores= [0, 1, 2, 3, 4]

try:
    valor = divisores[indice]
except IndexError:
    print('Lo sentimos, no es posible acceder a dicho índice.')

Dentro del bloque try colocaremos todas aquellas líneas de código que intentaremos ejecutar. Utilizo la palabra intentar ya que es posible que en dichas líneas ocurra un error.

Para lidiar con el error definiremos el bloque except, Este bloque se conforma por la palabra reservada except seguida por el tipo de error. Para este ejemplo IndexError. Con esto le indicamos a Python que, en caso exista un error de tipo IndexError se ejecute todo el código que se encuentra dentro del bloque.

Esto funciona bastante bien, sin embargo existe un pequeña limitante, el bloque de error solo se ejecutará cuando ocurra 'ese' error en particular.

divisores= [0, 1, 2, 3, 4]
indice = 0

try:
    divisor = divisores[indice]
    100 / divisor 

except IndexError:
    print('Lo sentimos, no es posible acceder a dicho índice.')

Para este segundo ejemplo hemos añadido una pequeña sentencia más. Intentamos obtener el valor de un indicie, y, si esto es posible, realizamos una división.

En teoría todo debería funcionar, sin embargo (para mi ejemplo) el primer valor es 0, por lo tanto se intenta dividir el número sobre 0, lo cual ocasiona un error.

Traceback (most recent call last):
  File "main.py", line 7, in <module>
    valor / 0
ZeroDivisionError: division by zero

Para validar este posible error, lo recomendable es definir un nuevo bloque except.

lista = [0, 1, 2, 3, 4]
indice = 0

try:
    valor = lista[indice]
    100 / 0

except IndexError:
    print('Lo sentimos, no es posible acceder a dicho índice.')

except ZeroDivisionError:
    print('Lo sentimos, no es posible realizar la división.')

El código, aun que más extenso, es mucho más seguro y legible.

El código intenta realizar un par de acciones, y si estas no pueden ser completadas se ejecutarán los bloques de errores.

Como puedes observar, en Python es posible utilizar una N cantidad de bloques except para un bloque try, pudiendo así definir acciones muy puntuables sobre cada tipo de error. Por ejemplo, si el error de tipo X ocurre, entonces notificamos a los administradores por correo electrónico, si el error de tipo Y ocurre entonces registramos un nuevo log de errores. Solo por mencionar un par de ejemplos que se me vienen a la mente. 🤓

Exception

En el caso que no queramos definir acciones individuales por cada tipo de error, y necesitemos realizar una sola tarea, indepentiendemte del tipo de error, haremos uso del tipo de Exception.

Exception no es más que la clase Padre de la cual heredan todas las demás excepciones. Por lo tanto, funciona de forma estupenda para validar errores independientemente de su tipo. 🤠

Nuestro código, utilizando Exception, pudiera quedar de la siguiente manera..

lista = [0, 1, 2, 3, 4]
indice = 0

try:
    valor = lista[indice]
    100 / 0

except Exception:
    print('Lo sentimos, no fue posible completar la tarea')

Ahora solo debemos asegurarnos que el código dentro del bloque except sea lo suficientemente abstracto para que funcione para todos los tipos de errores. 😋

Si bien usar Exception es una practica habitual (y no le veo nada de malo), creo que si tienes bien identificado el posible error, lo mejor que puedes hacer es trabajar con dicho error y dejar aun lado la abstracción. 🧐🍻

Uso de errores

Bien, como hemos visto a lo largo de esta entrega es posible manejar los errores mediante los bloques try y except, pero ¿Qué pasa si debemos utilizar el error per se? 😲 Bueno para ello definiremos una nueva variable en el bloque except.

try:
    valor = lista[indice]
    100 / 0

except Exception as error:
    print('Lo sentimos, no fue posible completar la tarea')
    print('El error fue:', error) 

En el bloque except, después de definir el tipo de error, obtendremos el error médiate la palabra reservada as. Para este ejemplo el error es almacenado en la variable error, variable que, por supuesto, puede ser utilizada en el bloque de except.

Esta variable nos permitirá conocer en detalle el error suscitado. Puntualmente su mensaje.

python main.py
Lo sentimos, no fue posible completar la tarea
El error fue: division by zero

Esto funciona bastante bien cuando queremos notificar el mensaje de error. 🚨

Bloques extras. 🐍

Hasta ahora hemos trabajado con 2 bloques, try y catch, pero ¿Qué pensarías si te dijera que existen un par de bloques más que podemos utilizar al momento de manejar los errores? 🤯

Me refiero a los bloques else y finally, bloques completamente opcionales.

Estos bloques nos permitirán, respectivamente, ejecutar código cuando no exista ningún tipo error y cuando todas las operaciones hayan concluido.

lista = [0, 1, 2, 3, 4]
indice = 1

try:
    valor = lista[indice]
    resultado = 100 / 0

except Exception as error:
    print('El error fue:', error)

else:
    print("El resultado es: ", resultado)

finally:
    print('La operación ha finalizado (Con o sin errores).')

Para este nuevo ejemplo tenemos 2 opciones posibles.

1.- Se intenta obtener un elemento de la lista y se intenta realizar una división. Si estas operaciones se realizan sin ningún tiempo de error, se imprime en consola el resultado de la operación junto con el mensaje: La operación ha finalizado (Con o sin errores).

2.- Se intenta obtener un elemento de la lista y se intenta realizar una división. Si estas operaciones no pueden ser completadas, se imprime en pantalla el error junto con el mensaje: La operación ha finalizado (Con o sin errores).

Como puedes observar, en el bloque else colocaremos todas aquellas líneas de código que deseemos ejecutar cuando no ocurra ningún error. Por su parte, en el bloque se finally colocaremos todas aquellas líneas de código que deseemos ejecutar, indepentiendemte si ocurrió o no un error. 👾

Ojo, es importante mencionar que el orden de estos bloques siempre será el siguiente.

  • try: Bloque donde intentaremos algo.
  • except: Bloque donde lidiaremos con el error.
  • else: Bloque donde ejecutaremos código siempre y cuando no haya existido ningún tipo de error.
  • finally: Bloque que se ejecutara independientemente si ocurrió o no un error.

Recuerda, else y finally son opcionales.

Conclusión

Listo, ahora ya sabes qué son las excepiones y como puedes manejarlas en Python. Recuerda, los errores no son algo que podamos evitar, así que mejor trabajemos con ellos, aprendamos a convivir justo, y para ellos los bloques try, excep, else y finally sin duda nos serán de mucha utilidad. 🍻

Si te interesa continuar con el tema de excepciones te comparto un segundo post donde aprendemos a crearlas.


¿El contenido te resulto de ayuda?

Para poder dejar tu opinión es necesario ser un usuario autenticado. Login

Albertusortiz

Muy clara la explicación de excepciones, siempre he usado try-catch, pero no tenia claro el Core de esta funcionalidad.

Gracias.

Más Tips y Ejercicios 🐍

Adquiere una subscripción PyWombat por tan solo $3 USD. al mes.

Conoce los beneficios de ser usuario premium:
Niveles desbloqueados: Ten accesos a todos los niveles de ejercicios. 🔓
Nuevo límite: Incrementa tu límite de ejercicios por semana. 🚀
Contenido único: Recibe semanalmente recursos exclusivos de Python (Videos, Artículos y Capitulos del libro PyWombat, comienza como desarrollador Python. 🐍