Excepciones en Python ▷ Manejo de errores (Try / Except / Finally)

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.

¿Para qué sirve manejar las excepciones en python?

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 de 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
#  
#  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 by zero
Error de division by zero calculadora.py

Error de división por cero:


Traceback (most recent call last):
File "test.py", line 48, in
dividir()
File "test.py", line 20, in dividir
x = a / b
ZeroDivisionError: division by zero

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 a manejar errores, 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 identando todo el código debajo del Try: (utilizando la tecla tab agregamos una identació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
#  
#  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. 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:

except ZeroDivisionError:

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
#  
#  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 aun hay mas! 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 halla 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
#  
#  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 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 lenguaje 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.

Traceback (most recent call last):
File "test.py", line 48, in
dividir()
File "test.py", line 20, in dividir
x = a / b
ZeroDivisionError: division by zero

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.

 

Más!

Me gustaría dejarte una serie de artículos donde se encuentra muy bien explicado cómo abordar los errores comunes que puedan surgirnos a menudo:

Errores y excepciones

Mensajes Excepcionales

 

Aserciones

Definición

Una aserción es una comprobación de validez (traducido al español como “afirmar”) que puedes prender o apagar cuando hallas 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 programacion, 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.

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 ejemplos de su 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.

Adiooos!
Y esto ha sido todo, 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!

 

 

 

 

Ayudame compartiendo este blog de programación