Saltar al contenido
Control Automático Educación

Manejo de Errores en Python

En esta entrada comenzaremos a entender el manejo de errores en Python, como podemos interpretarlo y posibles formas de encontrar una solución a los Scripts que vayamos creando.

Antes de comenzar te invito para que veas nuestro Curso Gratuito de Python desde Cero.

Y que te suscribas al canal, si te gusta la programación, electrónica y la teoría del control:

Manejo de Errores en Python

En nuestra vida como programadores es muy común cometer errores en nuestro código, lo importante es no desesperarnos y saber como resolverlos. Para eso será importante tener un buen manejo de errores en python para poder encontrar la solución.

Entre los errores comunes en python de python tenemos:

  • ERRORES SINTÁCTICOS: Se producen cuando existe un problema de sintaxis en nuestros comandos, como digitar mal un comando, y Python nos alerta de esto con el mensaje de error SyntaxError: invalid syntax.
  • ERRORES EN TIEMPO DE EJECUCIÓN: Ocurren mientras el programa se está ejecutando y algo inesperadamente ocurre mal. Generalmente Python nos informa ese tipo de error como por ejemplo una recursión infinita causando el error máximum recusrion Depth exceded.
  • ERRORES SEMÁNTICOS: Se dan cuando el programa compila y se ejecuta normalmente, pero no hace lo que se pretendía que hiciera y Python en este caso no nos va informar donde está el error. Y para eso debemos valernos de la depuración.

¿Cómo manejar los errores en Python?

Python al igual que muchos otros lenguajes de programación nos permiten encontrar y solucionar los errores de código dependiendo de su naturaleza. Veremos que para manejar los errores en python podemos hacerlo mediante la correcta lectura de los TraceBack, usando print statement, empleando el debugger del IDE que estemos usando, y realizando un correcto manejo de excepciones con los comandos Try-Except-Raise-Else-Finally.

ERRORES SINTÁCTICOS

Cuando empleamos un lenguaje de programación como por ejemplo Python, será común caer en este tipo de error, pues los errores de sintaxis, o sintácticos, ocurren cuando el programador escribe los comandos dentro del código que no son acordes con las reglas de escritura estipuladas para el empleo del lenguaje de programación.

Los errores de sintaxis siempre son detectados por el intérprete de Python antes de ejecutar el programa, por lo que son errores relativamente simples de resolver.

Estos errores de tipografía nos pueden indicar si el nombre de algun comando es incorrecto, nombres de variables incorrectas, si falta algún paréntesis, palabras claves mal escritas, etc.

A continuación veremos un listado con todas las verificaciones que podremos realizar para la corrección de errores sintácticos o de Sintaxis (Syntax Error en Python):

  • Se corrigen leyendo el mensaje de error arrojado por Python, a pesar que muchas veces no nos indique exactamente donde está el error.
  • Muchas veces el error ocurre NO en la línea que indica Python, sino en la línea inmediatamente anterior.
  • Verificar que no se crean variables con palabras reservadas de Python
  • Verificar los dos puntos al final de instrucciones como for, while, def, if y clases.
  • Verificar la identación y que sea consistente.
  • Verificar que los strings estén encerrados entre comillas. O cadenas multilíneas pues puede generar el error invalid token.
  • Verificar cerrar todos los paréntesis, llaves y corchetes
  • Verificar si no se confundió el = por ==

Ejemplo de Syntax Error en Python

El siguiente Script tiene errores de syntaxis escritos de forma proposital. La idea aquí es que puedas leer los errores arrojados por el interprete de python y consigas darle un manejo adecuado a estos errores.

"""
Errores de sintaxis

"""


def main():
    divisor = 5
    for i in range(100):
        if i % divisor = 0
            print(f'{i} is divisible by {divisor')


if __name__ == '__main__':
    main()

Si observamos tenemos los siguientes errores sintácticos en python que el propio interprete nos dice la ubicación de los errores:

  • En la linea 10, en el condicional hace falta un =, dado que en la lógica debemos usar el comando de igualdad y no el comando de asignación. if i % divisor == 0
  • En la linea 10, dado que estamos en un condicional, es necesario finalizar con dos puntos ( : ), if i % divisor == 0:
  • En la linea 11, el syntax error de python nos indica que falta un ‘}’, el cual está faltando al final del mensaje del print con formato. print(f'{i} is divisible by {divisor’})
Función ZIP Python

La Función zip() en Python

Display 7 Segmentos MicroPython

Display 7 Segmentos

Tipos Primitivos en Python

Tipos de Datos

ERRORES EN TIEMPO DE EJECUCIÓN

En los errores de tiempo de ejecución (excepciones) Python compila y ejecuta el programa pues no hay errores de sintaxis.

Si el programa no hace nada, asegúrese de estar llamando las funciones en su principal y por supuesto de estar imprimiendo lo que desea ver con su código.

Si el programa se detiene y parece no hacer nada puede que este atrapado dentro de un ciclo infinito, para verificar este problema, añada un print dentro del ciclo (esto se conoce como print “statement“) y otra fuera del ciclo para ver si sale.

Si existe recursión infinita puede aparecer el error RuntimeError:máximum recursión Depth exceded.

Si el programa arroja una excepción, en ese caso Python imprime un mensaje que incluye el nombre de la excepción y la línea donde ocurrió: Name error; Type Error; Key Error; Attribute Error; Index Error.

Cuando Python nos arroja un error, este va a mostrar un mensaje de error conocido como TraceBack, en este mensaje estarán detallados las informaciónes del error o la excepción que han impedido que Python ejecute o llegue al final del código programado.

La visión general de un TRACEBACK puede ser visto a continuación:

Traceback Python

La forma correcta de leer estos errores en Python (Traceback) es como lo indica la flecha amarilla, siempre de abajo hacia arriba.

Inicialmente, observe que en el recuadro verde, siempre va a aparecer el error o la excepción encontrada por Python. Este tipo de error puede ser por ejemplo el index error (no encuentra un indice en una lista, tupla, etc) pero también pueden existir otro tipo de errores tales como:

  • NameError
  • IndexError
  • KeyError
  • TypeError
  • valueError
  • ImportError /ModuleNotFound

Seguidamente, en el recuadro azul, podremos ver un resumen sobre el error detectado.

Si continuamos hacia arriba en el traceback, podremos notar la linea de código donde fue detectado el error y la linea de comando dentro del programa.

Finalmente en la primera linea aparece el Traceback donde aparce most recent call last, que indica que el error fue encontrado en el último módulo ejecutado en el programa de python.

El error de ese traceback de ejemplo fue generado con el siguiente código:

# Python program to demonstrate
# traceback
mylist = [1, 2, 3]
print(mylist[10])

Ejemplo de Excepción Recursion Error

En la entrada donde explicamos el funcionamiento del ENTRY POINT con Python, desarrollamos un ejemplo donde creamos una función que calcula el factorial de un número.

En este caso, vamos a crear esa misma función pero llamando la función recursivamente, esto quiere decir que la función se va a llamar a ella misma una y otra vez hasta encontrar la solución del número factorial.

Python, establece un limite máximo de 1000 donde permite que una función se llame a ella misma (recursión). Es decir que solo puede hacer el llamado 1000 veces. Si excedemos este limite, va a aparecer una excepción mostrado en un traceback mostrando el tipo de error: Recursion Error.

El siguiente código provoca ese error:

#Funcion por recursion
def factorial(n):
    if n == 0 or n == 1:
        return 1
    return n * factorial(n-1)
    # n = 3
    # 3! = 3 * 2!
    # 2! = 2 * 1!
    # 1! = 1  Base

if __name__ == '__main__':
    f = factorial(2000)
    print(f)

Para corregir el error, basta con configurarle a Python el limite máximo de recursión para otro valor, para eso será necesario llamar el módulo sys y posteriormente configurar el limite con el método setrecursionlimit:

import sys

#Funcion por recursion
def factorial(n):
    if n == 0 or n == 1:
        return 1
    return n * factorial(n-1)
    # n = 3
    # 3! = 3 * 2!
    # 2! = 2 * 1!
    # 1! = 1  Base

if __name__ == '__main__':
    sys.setrecursionlimit(4000)
    f = factorial(2000)
    print(f)

ERRORES SEMÁNTICOS

Los errores semánticos en Python, también llamados errores lógicos, son los mas difíciles de depurar dado que ni el compilador ni el sistema nos muestran un fallo o error. Si hay un error semántico en el script de python, este se ejecutará correctamente en el sentido de que el compilador no va a generar ningún mensaje de error. Sin embargo, el programa o script no hará lo correcto. Hará otra cosa. En otras palabras, el script hará lo que le usted le dijo que hiciera, no lo que usted quería que hiciera.

Existen dos formas directas de realizar el manejo de errores con python relacionados a los errores semánticos:

  • Usar los depuradores que le ofrece su IDE.
  • Usar print statement

Ejemplo de error semántico

Para poder ejemplificar el manejo de errores semánticos en Python, vamos a crear un script que sea capaz de encontrar las raíces de una ecuación cuadrática, para eso solucionaremos inicialmente la ecuación para posteriormente proceder a desarrollar el script.

La idea es solucionar una ecuación en la forma:

a\ x^2+b\ x + c = 0

Suponga que tenemos la siguiente ecuación:

x^2-5x +6 = 0

Solucionando, tenemos que:

x=\dfrac{-b\pm \sqrt{b^{2}-4ac}}{2a}
x=\dfrac{-(-5)\pm \sqrt{(-5)^{2}-(4)(1)(6)}}{(2)(1)}
x=\cfrac{5\pm \sqrt{25-24}}{2}
x=\cfrac{5\pm \sqrt{1}}{2}
x=\cfrac{5\pm 1}{2}

Por lo tanto, las raíces de la ecuación cuadrática son:

x_1=\cfrac{5+1}{2}=3
x_2=\cfrac{5-1}{2}=2

El siguiente Script en Python (el cual tiene un error semántico de forma proposital) busca encontrar las raíces de la ecuación cuadrática.

"""
Crear una función que sea capaz de encontrar las raíces de una ecuación cuadrática de la forma: 
by: Sergio Andres Castaño Giraldo
"""

def quadratic_equation(a, b, c):
    # calculate the discriminant
    d = (b*2) - (4*a*c)

    # find two solutions
    x1 = (-b-(d)**0.5)/(2*a)
    x2 = (-b+(d)**0.5)/(2*a)
    return x1, x2


if __name__ == '__main__':
    print('Python Program to Solve Quadratic Equation')

    a = float(input('Coefficients a: '))
    b = float(input('Coefficients b: '))
    c = float(input('Coefficients c: '))

    x1, x2 = quadratic_equation(a, b, c)

    print(f'The solution are {x1} and {x2}')

Si ejecutamos el código anterior, veremos que el script se ejecuta sin problemas, sin emnbargo el programa no hace lo que nosotros realmente queriamos, porque en este caso el programa nos dice que las raíces erroneamente son:

x_1=2.5-j2.91;\ \ \ x_2=2.5+j2.91

Para encontrar este error semántico, procedemos a emplear el debugger de Visual Studio Code o el debugger de Spyeder, o en otras palabras el Debugger del IDE que tú estés empleando.

Vamos a ir colocando los BreakPoint a lo largo del código y vamos a ir analizando las ventanas de variables para determinar donde se encuentra el error.

Si deseas ver como se configura el Debugger en Visual Studio Code: https://code.visualstudio.com/docs/python/debugging

Si vemos, el error del script se encuentra dentro de la función quadratic_equation al momento de calcular el discriminante.

Donde tenemos:

d = (b*2) - (4*a*c)

debemos sustituirlo por:

d = (b**2) - (4*a*c)

Dado que b debe estar elevado al cuadrado y NO multiplicado por 2.

MANEJO DE EXCEPCIONES

Siempre que ocurre un error en tiempo de ejecución, se crea una excepción. Normalmente el programa se PARA (STOP) y Python presenta un mensaje de error.

  • Por ejemplo, la división por cero crea una excepción:
print 55/0

ZeroDivisionError: Integer division or modulo

  • Un elemento no existente en una lista hace lo mismo:
a = []
print a[]

IndexError: list index out of range

  • O el acceso a una clave que no esta en el diccionario:
b = {}
print b['que']

KeyError: que

Try y Except en Python

A veces queremos realizar una operación que podría provocar una excepción, pero no queremos que se pare el programa. Podemos manejar la excepción usando las sentencias try y except (Intentar y excepto que,… haga…).

try:
    #Some code
except:
    #Executed if error in the try block

Algunas excepciones de Python son: NameError, ndexError, KeyError, TypeError, valueError, ImportError /ModuleNotFound

TRY: En el try se coloca código que esperamos que pueda lanzar algún error.


EXCEPT: En el except se maneja el error, es decir, si ocurre un error dentro del bloque de código del try, se deja de ejecutar el código del try y se ejecuta lo que se haya definido en el Except.

Cláusula ELSE

En Python, también puede usar la cláusula else en el bloque try-except que debe estar presente después de todas las cláusulas except. El código ingresa al bloque else solo si la cláusula try no genera una excepción.

try:
    #Some code
except:
    #Executed if error in the try block
else:
    # execute if no exception

Cláusula FINALLY

Python proporciona una palabra clave finally, que siempre se ejecuta después de try y except.

Este código siempre se ejecuta después de los otros bloques, incluso si hubo una excepción no detectada o una declaración de retorno en uno de los otros bloques. 

try:
    #Some code
except:
    #Executed if error in the try block
else:
    # execute if no exception
finally:
    #some code .... (always executed)

Cláusula RAISE

Podemos usar raise para lanzar una excepción si ocurre una condición. La declaración se puede complementar con una excepción personalizada.

Por ejemplo:

raise Exception(‘Mensaje’) 
raise ValueError(‘Mensaje’) 
raise TypeError(‘Mensaje’) 
raise NameError(‘Mensaje’) 

Ejemplo de Excepciones con Python

Crear una función que divida dos numeros que haga un manejo adecuado de las excepciones empleando las cláusulas try, except, else, finally y raise.

def divide(x, y):
    try:
        z = x / y
        if z < 0:
            raise ValueError("Sorry, no numbers below zero")
    except (ZeroDivisionError):
        print("Error with input arguments.")
        try:
            v = 1 / 'a'
        except TypeError:
            print("Error")
    except ValueError as ve:
        print(ve)
        
    else:
        return z
    finally:
        print("executing finally clause")

result = divide(12, -1)
print(result)

Eso es todo por la entrada del dia de hoy, espero les haya gustado y hayan aprendido algo nuevo. Si te ha servido el contenido de esta entrada, de los videos y los códigos de implementación y deseas apoyar mi trabajo invitandome a un café super barato, puedes hacerlo en el siguiente link:

👉 Invitar a Sergio a un Café ☕️

Que esten muy bien, nos vemos en la siguiente entrada.

Entradas relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Comentarios (2)

ese ejemplo de Execepciones en Python devuelve lo siguiente:
Sorry, no numbers below zero
executing finally clause
None
¿Porqué aparece ese None?

Responder

Hola Jovanny, es porque cuando llegamos a la linea del rise, mostramos aquel mensaje y devuelve un None es porque no retornamos nada de la función entonces la variable result no va a tener nada almacenado dentro de ella, por eso por defecto queda con None.

Responder