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:
- La última línea indica el tipo de excepción (
ZeroDivisionError
) y su mensaje. - Las líneas anteriores muestran la secuencia de llamadas de funciones que llevaron al error.
- 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.