
Llamamos excepciones en python a los errores generados por nuestro código fuente. Si alguna función de nuestro programa genera un error y esta no lo maneja el mismo se propaga hasta llegar a la función principal que la invoco y genera que nuestro programa se detenga.
Un buen programador implementa el manejo de errores correctamente, para evitar que los errores se propaguen y detengan la aplicación mostrando advertencias de esas que el usuario no entiende y cree que le has roto su ordenador.
🤔 ¿Para qué sirve manejar las excepciones en python?
Manejar los errores nos va a permitir evitar que nuestro programa deje de funcionar de golpe y nos va a dar la posibilidad de mostrar un error personalizado al usuario en vez de los clásicos errores del intérprete Python.
Para esto podemos recurrir a ciertas palabras reservadas como vimos anteriormente en los ejemplos que nos van a permitir realizar algunas acciones antes de detener nuestro programa por completo. Normalmente los errores pueden provenir de un error de cálculos o a veces el usuario ingreso un dato que nuestro código no es capaz de procesar, entre otros.
🚨 El bloque try / except:
Para esto vamos a tratar de ubicar el código que pueda ser capaz de producir un error dentro de un bloque Try que podría traducirse como «intenta:». En el caso de generarse un error este buscara alguna especificación para el mismo en el bloque except.
Es decir que mediante el uso de Try/Except se logra establecer una condición en caso de que se generará un error dentro del bloque Try, siendo así debería dispararse el código que se encuentra en el Except. En caso de no haber error se continuaría normalmente!.. Las excepciones en Python son un tema quizás a veces difícil de comprender del todo, pero sin duda te serán muy útiles para darle un acabado profesional a cualquier programa y prevenir que este se detenga en caso de un error.
Como podemos ver en el siguiente código de nuestra calculadora si se produjera algún error en la entrada de usuario se mostrará un print («Error») :
#!/usr/bin/env python # -*- coding: utf-8 -*- # # calc.py - Excepciones en Python # # Copyright https://pythones.net # ############################################-1-################################################## def sumar(): #Definimos la función sumar x = a + b print (("Resultado"), (x)) def restar():#Definimos la función restar x = a - b print (("Resultado"), (x)) def multiplicar():#Definimos la función multiplicar x = a * b print (("Resultado"), (x)) def dividir():#Definimos la función dividir x = a / b print (("Resultado"), (x)) ##########################################-2-################################################### while True: #Creamos un bucle try: #Intentamos obtener los datos de entrada a = int(input("Ingresa el primer numero: n")) #Solicitamos el 1er numero al usuario b = int(input("Ingresa el segundo numero: n"))#Solicitamos el 2do numero al usuario print (("Que calculo quieres realizar entre"), (a), ("y"), (b), ("?n")) #Preguntamos el calc op = str(input(""" #Ofrecemos las opciones de cálculo las cuales van a llamar a las funciones 1- Sumar 2- Restar 3- Multiplicar 4- Dividir n""")) except: #En caso de error: print ("Error") op = '?' ##########################################-3-################################################## if op == '1':#Si el usuario elige opción 1 llamamos a sumar sumar() break elif op == '2':#Si el usuario elige opción 1 llamamos a restar restar() break elif op == '3':#Si el usuario elige opción 1 llamamos a multiplicar multiplicar() break elif op == '4':#Si el usuario elige opción 1 llamamos a dividir dividir() break else: print ("""Has ingresado un numero de opción erroneo""") #En caso que el numero no #se encuentre
Atención:
Aquí se encuentra resaltado el bloque Try y el except. Pero en este caso dentro del bloque Try solo se encuentran los datos de entrada del usuario? Te has fijado? Esto nos está cubriendo en caso de que el usuario ingresara caracteres extraños, pero.. Qué sucedería ahora si el usuario ejecutando nuestro programa intenta dividir por cero?? Es decir ingresa como primer número un entero cualquiera y como segundo un cero eligiendo la opción dividir.. Haz la prueba!
Pues sucede esto:
❗ Error de división por cero:
ZeroDivisionError: division by zero
Traceback (most recent call last):
File "test.py", line 48, in
dividir()
File "test.py", line 20, in dividir
x = a / b
Nuestro programa expone un FAIL! grande como una casa!! Y tu creiste que era perfecto? que no era vulnerable al usuario? Pues no, nuestra calculadora está llena de bugs y es una porquería inútil!.
Este try/except está mal!
Pero calma, para eso estamos aprendiendo excepciones en python, ahora vamos a corregir estos problemas. El error de división por cero es un clásico. Venga vamos a solucionarlo!
Para solucionar este inconveniente del usuario pretencioso vamos a meter todo el cuerpo del bucle while dentro del try y vamos a crear múltiples bloques except. Esto lo hacemos principalmente indentando todo el código debajo del Try: (utilizando la tecla tab agregamos una indentación de 4 espacios) y suprimiendo el except para colocarlo al final de nuestro código, lo que nos quedaria asi:
#!/usr/bin/env python # -*- coding: utf-8 -*- # # calc.py - Excepciones en Python # # Copyright https://pythones.net # ############################################-1-################################################## def sumar(): #Definimos la función sumar x = a + b print (("Resultado"), (x)) def restar():#Definimos la función restar x = a - b print (("Resultado"), (x)) def multiplicar():#Definimos la función multiplicar x = a * b print (("Resultado"), (x)) def dividir():#Definimos la función dividir x = a / b print (("Resultado"), (x)) ##########################################-2-################################################### while True: #Creamos un bucle try: #Intentamos obtener los datos de entrada a = int(input("Ingresa el primer numero: n")) #Solicitamos el 1er numero al usuario b = int(input("Ingresa el segundo numero: n"))#Solicitamos el 2do numero al usuario print (("Que calculo quieres realizar entre"), (a), ("y"), (b), ("?n")) #Preguntamos el calc op = str(input(""" #Ofrecemos las opciones de cálculo las cuales van a llamar a las funciones 1- Sumar 2- Restar 3- Multiplicar 4- Dividir n""")) ##########################################-3-################################################## if op == '1':#Si el usuario elige opción 1 llamamos a sumar sumar() break elif op == '2':#Si el usuario elige opción 1 llamamos a restar restar() break elif op == '3':#Si el usuario elige opción 1 llamamos a multiplicar multiplicar() break elif op == '4':#Si el usuario elige opción 1 llamamos a dividir dividir() break else: print ("""Has ingresado un numero de opcion erroneo""") #En caso que el numero no #se encuentre except: print ("Error") op = '?'
Aquí puedes ver resaltado todo el código que se encuentra dentro del Try y el except.
Ahora si el usuario intenta salir del bucle con las teclas «ctrl + x» o bien intenta dividir por cero se muestra el error personalizado «Error» y se vuelve al comienzo del bucle por lo que volverá a pedirle que ingrese un número. Si sabemos manejar excepciones en python ya no se podrá reír en nuestra cara!! Pero nosotros vamos a ser más pretenciosos y vamos a mostrarle al usuario que es lo que está haciendo mal y dándole la advertencia que en este caso nuestra calculadora no permite dividir por cero modificando el except para atrapar el error «division by zero» que nos salía al principio.
🚨 Except:
Porque por si no te lo dije puedes poner solo un except en general para cualquier error o puedes crear múltiples except para cada error particular lo que nos permitirá anticiparnos a estos y generar una advertencia o corrección para cada uno!
El except puede traducirse como «excepción» y sirve para atrapar el error generado dentro del bloque try y permitirnos manejarlo para evitar el cierre brusco de nuestro programa mostrando un error típico del intérprete!
Bien, ahora que sabemos esto vamos a crear un except exclusivo para el error «Division by zero»
Para eso solo basta con agregar el bloque:
ZeroDivisionError:except
Antes del except general.
Y debajo de él la advertencia que queremos mostrar o el código a ejecutar en caso de darse este error quedando nuestro código final así:
#!/usr/bin/env python # -*- coding: utf-8 -*- # # calc.py - Excepciones en python # # Copyright https://pythones.net # ############################################-1-################################################## def sumar(): #Definimos la función sumar x = a + b print (("Resultado"), (x)) def restar():#Definimos la función restar x = a - b print (("Resultado"), (x)) def multiplicar():#Definimos la función multiplicar x = a * b print (("Resultado"), (x)) def dividir():#Definimos la función dividir x = a / b print (("Resultado"), (x)) ##########################################-2-################################################### while True: #Creamos un bucle try: #Intentamos obtener los datos de entrada a = int(input("Ingresa el primer numero: n")) #Solicitamos el 1er numero al usuario b = int(input("Ingresa el segundo numero: n"))#Solicitamos el 2do numero al usuario print (("Que calculo quieres realizar entre"), (a), ("y"), (b), ("?n")) #Preguntamos el calc op = str(input(""" #Ofrecemos las opciones de cálculo las cuales van a llamar a las funciones 1- Sumar 2- Restar 3- Multiplicar 4- Dividir n""")) ##########################################-3-################################################## if op == '1':#Si el usuario elige opción 1 llamamos a sumar sumar() break elif op == '2':#Si el usuario elige opción 1 llamamos a restar restar() break elif op == '3':#Si el usuario elige opción 1 llamamos a multiplicar multiplicar() break elif op == '4':#Si el usuario elige opción 1 llamamos a dividir dividir() break else: print ("""Has ingresado un numero de opcion erroneo""") #En caso que el numero no #se encuentre except ZeroDivisionError: print ("Nuestro calculador no permite dividir por cero, intenta otro calculo!") except: print ("Error") op = '?'
Y con esto no habremos solucionado el error de nuestra calculadora. Pero al menos brindamos un error personalizado y evitamos que se detenga el bucle de golpe.
Recuerda que el bloque except para cada error particular debe ir siempre antes del except general, como ves en el código más arriba!! De lo contrario generaremos un error de sintaxis!
Pero aún hay más dentro de las excepciones en python! Tenemos el bloque finally
❌ Finally:
El bloque finally que puede traducirse como «finalizando» nos permite indicar las sentencias de finalización con la particularidad de que se ejecutan haya surgido o no un error. Si hay un bloque finally no es necesario el except y podemos aplicar un try, solo con un finally.
En nuestra calculadora podríamos agregarlo al final así:
finally:
print ("Gracias por utilizar nuestra calculadora")
Para que luego de utilizar nuestro programa (surja o no un error) muestre este mensaje de agradecimiento.
Bien ahora voy a colocar el código final completo en caso de que quieras guardarlo o utilizarlo
#!/usr/bin/env python # -*- coding: utf-8 -*- # # calc.py - Excepciones en python - Finally # # Copyright https://pythones.net # ############################################-1-################################################## def sumar(): #Definimos la función sumar x = a + b print (("Resultado"), (x)) def restar():#Definimos la función restar x = a - b print (("Resultado"), (x)) def multiplicar():#Definimos la función multiplicar x = a * b print (("Resultado"), (x)) def dividir():#Definimos la función dividir x = a / b print (("Resultado"), (x)) ##########################################-2-################################################### while True: #Creamos un bucle try: #Intentamos obtener los datos de entrada a = int(input("Ingresa el primer numero: n")) #Solicitamos el 1er numero al usuario b = int(input("Ingresa el segundo numero: n"))#Solicitamos el 2do numero al usuario print (("Que calculo quieres realizar entre"), (a), ("y"), (b), ("?n")) #Preguntamos el calc op = str(input(""" #Ofrecemos las opciones de cálculo las cuales van a llamar a las funciones 1- Sumar 2- Restar 3- Multiplicar 4- Dividir n""")) ##########################################-3-################################################## if op == '1':#Si el usuario elige opción 1 llamamos a sumar sumar() break elif op == '2':#Si el usuario elige opción 1 llamamos a restar restar() break elif op == '3':#Si el usuario elige opción 1 llamamos a multiplicar multiplicar() break elif op == '4':#Si el usuario elige opción 1 llamamos a dividir dividir() break else: print ("""Has ingresado un numero de opcion erroneo""") #En caso que el numero no #se encuentre except ZeroDivisionError: print ("Nuestro calculador no permite dividir por cero, intenta otro calculo!") except: print ("Error") op = '?' finally: print ("Gracias por utilizar nuestra calculadora")
Hasta ahora hemos aprendido a prevenir y solucionar el cierre repentino de nuestro programa utilizando excepciones en python (try / except / finally).
🔥 Tipos de errores en Python y cómo solucionarlos:
Los traceback en español (Trazas de rastreo) son la información que el intérprete recopila sobre el error que ha ocurrido. Si les prestamos la atención suficiente seremos capaces de comprender el porqué y donde se comete el error en nuestro código.
ZeroDivisionError
Este es el error que corregimos anteriormente, normalmente se produce cuando se intenta dividir por cero.
ZeroDivisionError: division by zeroTraceback (most recent call last):
File "test.py", line 48, in
dividir()
File "test.py", line 20, in dividir
x = a / b
Si prestamos atención al Traceback será lo que nos brindara la información acerca del error y en que linea se cometió. Lo que nos permite corregirlo o crear una excepción con mayor facilidad!
NameError
En este caso intente ejecutar el siguiente código:
while True: print (a)
Y el intérprete nos dispara el siguiente error:
Traceback (most recent call last):
File «test.py», line 2, in <module>
print (a)
NameError: name ‘a’ is not defined
Este error nos está diciendo que se hizo una llamada a un elemento que no existe (o aún no fue definida), que en este caso es la variable «a», como puedes ver en el código nunca la definimos y por ende el intérprete no sabe qué nos referimos a una variable. Pero a veces los errores NameError también se deben a un error de sintaxis, por ejemplo si pusiéramos el «True» del bucle While en minúscula, este nos dispararía un error así:
Traceback (most recent call last):
File «test.py», line 1, in <module>
while true:
TypeError
Si intentamos ejecutar el siguiente código sumando una variable de número entero con una de tipo texto nos producirá el siguiente error:
a = 12 b = 'Hola' print (a + b)
Traceback (most recent call last):
File «test.py», line 3, in <module>
print (a + b)
TypeError: unsupported operand type(s) for +: ‘int’ and ‘str’
Debido a que intentamos sumar dos variables de tipos incompatibles.
✅ Aserciones
Definición
Una aserción es una comprobación de validez (traducido al español como «afirmar») que puedes prender o apagar cuando hayas terminado de probar el programa. Una expresión es probada y si el resultado es falso una excepción es levantada.
Casi podría decirse que hacemos una comprobación y en caso de ser falsa se genera un error que podemos personalizar para detectar el fallo rápidamente.
🖋️ Sintaxis de las aserciones
Las aserciones son llevadas a cabo a partir de la sentencia «assert«, vamos a ver un ejemplo, en este caso utilizando condiciones if para comprobar las monedas de las que dispone un usuario, pero también queremos comprobar que no sea un número negativo, y en caso que lo sea detener el programa enviando un error.
#!/usr/bin/env python # -*- coding: utf-8 -*- # # assert.py # # Copyright 2018 https://pythones.net monedas = -19 if monedas >= 12: print (("Tienes"), (monedas), (",que es más que 12")) elif monedas <= 12: print (("Tienes"),(monedas),(",que es menos que 12, lo siento consigue más monedas")) assert monedas > 0, "Error de comprobación, monedas es negativo"
Como vemos se coloca la sentencia «assert» seguido de la condición en la que se ejecutará y luego después de la coma entre comillas el error que le será mostrado al usuario o programador.
A menudo la sentencia assert se utiliza para comprobar errores de programación, si tu estas realizando un programa con mucho código y quieres ir comprobando que todo funcione como es correcto lo puedes utilizando aserciones, lo que te permitirá detectar rápidamente donde se produce un error. El uso de excepciones en python normalmente es lo que también es parte del proceso de debugging ya que nos facilita encontrar errores en nuestra aplicación.
En el ejemplo anterior podría decirse que habremos cometido un error anteriormente que le permite al usuario tener la variable monedas en negativo.
➡️ Otros casos de uso
Las aserciones nos sirven como pre y post condiciones en métodos, funciones, bloques de código pero sobre todo para especificar invariantes. Es más corto que escribir una sentencia if, y más claro para el que lo lee siempre y cuando deseemos que la sentencia no se ejecute y el programa finalice.
Y esto ha sido todo sobre excepciones en python, ya aprendimos a manejar los posibles errores, nos vemos en la siguiente entrada y espero que te halla sido muy útil! No olvides suscribirte a mi blog si estas aprendiendo o eres programador en Python. Salute!