Ir al contenido principal

Tipos de errores en Python

Introducción

Cuando programamos en Python, es inevitable encontrarnos con errores. Estos errores, técnicamente llamados excepciones, interrumpen la ejecución normal de nuestro programa cuando se detecta alguna situación problemática. Comprender los diferentes tipos de errores que pueden ocurrir es fundamental para escribir código más robusto y para poder manejarlos adecuadamente. En este artículo, exploraremos los principales tipos de errores que podemos encontrar en Python y aprenderemos a identificarlos cuando aparezcan en nuestro código.

Errores de sintaxis vs. excepciones

En Python, podemos distinguir dos categorías principales de errores:

Errores de sintaxis (SyntaxError)

Los errores de sintaxis ocurren cuando el intérprete de Python no puede entender el código porque viola las reglas gramaticales del lenguaje. Estos errores se detectan durante la fase de análisis, antes de que el programa comience realmente a ejecutarse.

# Error de sintaxis: falta el paréntesis de cierre
print("Hola mundo"

Cuando ejecutamos este código, Python nos mostrará un mensaje como:

  File "ejemplo.py", line 2
    print("Hola mundo"
                     ^
SyntaxError: unexpected EOF while parsing

Los errores de sintaxis deben corregirse antes de que el programa pueda ejecutarse. El intérprete generalmente nos indicará dónde está el problema y dará una pista sobre cuál es el error.

Excepciones

Las excepciones, por otro lado, son errores que ocurren durante la ejecución del programa. El código es sintácticamente correcto, pero al ejecutarlo surge algún problema.

# Este código es sintácticamente correcto, pero generará una excepción
numero = int("texto")  # Intentamos convertir texto a número

Al ejecutar este código, Python producirá un error como:

Traceback (most recent call last):
  File "ejemplo.py", line 2, in <module>
    numero = int("texto")
ValueError: invalid literal for int() with base 10: 'texto'

Tipos comunes de excepciones en Python

Python tiene una gran variedad de excepciones predefinidas. A continuación veremos las más comunes:

ValueError

Ocurre cuando una función recibe un argumento con el tipo correcto pero un valor inapropiado.

int("42")    # Funciona correctamente
int("cuarenta y dos")  # Genera ValueError

TypeError

Se produce cuando intentamos realizar una operación con un tipo de dato inapropiado.

"5" + 5  # TypeError: no se puede sumar un string y un entero

NameError

Aparece cuando intentamos usar una variable o función que no ha sido definida.

print(variable_inexistente)  # NameError: name 'variable_inexistente' is not defined

IndexError

Sucede cuando intentamos acceder a un índice que no existe en una secuencia.

lista = [1, 2, 3]
print(lista[5])  # IndexError: list index out of range

KeyError

Similar al IndexError, pero para diccionarios cuando intentamos acceder a una clave que no existe.

diccionario = {"nombre": "Ana", "edad": 25}
print(diccionario["ciudad"])  # KeyError: 'ciudad'

ZeroDivisionError

Se produce cuando intentamos dividir por cero.

resultado = 10 / 0  # ZeroDivisionError: division by zero

FileNotFoundError

Ocurre cuando intentamos abrir un archivo que no existe.

archivo = open("archivo_inexistente.txt", "r")  # FileNotFoundError

ImportError/ModuleNotFoundError

Aparece cuando hay problemas al importar un módulo.

import modulo_inexistente  # ModuleNotFoundError: No module named 'modulo_inexistente'

AttributeError

Sucede cuando intentamos acceder a un atributo o método que no existe.

texto = "hola"
texto.append("mundo")  # AttributeError: 'str' object has no attribute 'append'

IndentationError

Ocurre cuando la indentación (sangría) del código no es correcta.

def funcion():
print("Mal indentado")  # IndentationError: expected an indented block

Jerarquía de excepciones

Las excepciones en Python están organizadas en una jerarquía. La clase base para todas las excepciones es BaseException, pero normalmente trabajaremos con Exception y sus subclases.

BaseException
 ├── SystemExit
 ├── KeyboardInterrupt
 ├── GeneratorExit
 └── Exception
      ├── StopIteration
      ├── ArithmeticError
      │    ├── FloatingPointError
      │    ├── OverflowError
      │    └── ZeroDivisionError
      ├── AssertionError
      ├── AttributeError
      ├── BufferError
      ├── EOFError
      ├── ImportError
      │    └── ModuleNotFoundError
      ├── LookupError
      │    ├── IndexError
      │    └── KeyError
      ├── MemoryError
      ├── NameError
      │    └── UnboundLocalError
      ├── OSError
      │    ├── BlockingIOError
      │    ├── ChildProcessError
      │    ├── ConnectionError
      │    │    ├── BrokenPipeError
      │    │    ├── ConnectionAbortedError
      │    │    ├── ConnectionRefusedError
      │    │    └── ConnectionResetError
      │    ├── FileExistsError
      │    ├── FileNotFoundError
      │    ├── InterruptedError
      │    ├── IsADirectoryError
      │    ├── NotADirectoryError
      │    ├── PermissionError
      │    ├── ProcessLookupError
      │    └── TimeoutError
      ├── ReferenceError
      ├── RuntimeError
      │    ├── NotImplementedError
      │    └── RecursionError
      ├── SyntaxError
      │    └── IndentationError
      │         └── TabError
      ├── SystemError
      ├── TypeError
      ├── ValueError
      │    └── UnicodeError
      │         ├── UnicodeDecodeError
      │         ├── UnicodeEncodeError
      │         └── UnicodeTranslateError
      └── Warning

Esta jerarquía es importante cuando manejamos excepciones, ya que podemos capturar tipos específicos o grupos de excepciones relacionadas.

El traceback: interpretando los mensajes de error

Cuando ocurre una excepción, Python nos muestra un traceback (traza de pila) que es esencial para entender qué salió mal y dónde. Vamos a analizar un ejemplo:

def dividir(a, b):
    return a / b

def calcular():
    resultado = dividir(10, 0)
    return resultado

try:
    calcular()
except Exception as e:
    print(f"Error: {e}")
    import traceback
    traceback.print_exc()

El traceback resultante sería:

Error: division by zero
Traceback (most recent call last):
  File "ejemplo.py", line 9, in <module>
    calcular()
  File "ejemplo.py", line 5, in calcular
    resultado = dividir(10, 0)
  File "ejemplo.py", line 2, in dividir
    return a / b
ZeroDivisionError: division by zero

El traceback se lee de abajo hacia arriba:

  1. La última línea indica el tipo de excepción (ZeroDivisionError) y su mensaje.
  2. Las líneas anteriores muestran la secuencia de llamadas de funciones que llevaron al error.
  3. Cada línea incluye el archivo, número de línea, nombre de la función y el código de esa línea.

Resumen

Comprender los diversos tipos de errores en Python es fundamental para escribir código más robusto y para solucionar problemas eficientemente. Los errores de sintaxis ocurren antes de la ejecución del programa, mientras que las excepciones ocurren durante la ejecución. Python ofrece una amplia variedad de excepciones predefinidas para diferentes situaciones problemáticas, desde errores de valor hasta problemas con archivos o índices.

En el próximo artículo, aprenderemos cómo manejar estas excepciones utilizando bloques try-except, lo que nos permitirá controlar los errores en lugar de permitir que interrumpan completamente nuestro programa.