Python

Python

Tutorial Python: Excepciones

Aprende a manejar excepciones en Python con try-except, else, finally y cómo lanzar errores para código robusto y seguro.

Aprende Python y certifícate

Try-except

En Python, los errores durante la ejecución de un programa se denominan excepciones. Cuando ocurre un error, el programa normalmente se detiene y muestra un mensaje de error. Sin embargo, en muchas situaciones, queremos que nuestro programa continúe funcionando incluso cuando se produce un error. Aquí es donde entra en juego el manejo de excepciones mediante la estructura try-except.

Podemos pensar en el manejo de excepciones como un "plan B" para nuestro código. Es como decir: "Intenta hacer esto, pero si algo sale mal, haz esto otro en su lugar".

La sintaxis básica de try-except es la siguiente:

try:
    # Código que podría generar una excepción
    # Se ejecuta normalmente
except:
    # Código que se ejecuta si ocurre una excepción
    # Es nuestro "plan B"

Veamos un ejemplo sencillo. Supongamos que queremos dividir dos números:

try:
    numero1 = 10
    numero2 = 0
    resultado = numero1 / numero2
    print(f"El resultado es: {resultado}")
except:
    print("¡Ups! No se puede dividir entre cero.")

En este ejemplo, intentamos dividir 10 entre 0, lo que generaría un error ZeroDivisionError. Sin embargo, en lugar de que el programa se detenga, el bloque except captura la excepción y muestra un mensaje amigable.

Capturando excepciones específicas

Es una buena práctica capturar tipos específicos de excepciones en lugar de usar un bloque except genérico. Esto nos permite manejar diferentes tipos de errores de manera diferente:

try:
    numero = int(input("Introduce un número: "))
    resultado = 100 / numero
    print(f"100 dividido por {numero} es {resultado}")
except ZeroDivisionError:
    print("No puedes dividir entre cero.")
except ValueError:
    print("Debes introducir un número válido.")

En este ejemplo, manejamos dos posibles excepciones:

  • ZeroDivisionError: si el usuario introduce 0
  • ValueError: si el usuario introduce algo que no se puede convertir a un entero

Accediendo a la información de la excepción

A veces, queremos acceder a la información detallada sobre la excepción que ocurrió. Podemos hacerlo asignando la excepción a una variable:

try:
    with open("archivo_inexistente.txt", "r") as archivo:
        contenido = archivo.read()
except FileNotFoundError as error:
    print(f"Error: {error}")
    print("Creando un archivo nuevo...")
    with open("archivo_inexistente.txt", "w") as archivo:
        archivo.write("Este es un archivo nuevo")

En este ejemplo, capturamos la excepción FileNotFoundError en la variable error y podemos acceder a su mensaje.

Combinando múltiples excepciones

Si queremos manejar varias excepciones de la misma manera, podemos agruparlas en una tupla:

try:
    # Intentamos abrir y leer un archivo
    archivo = open("datos.txt", "r")
    valor = int(archivo.readline().strip())
    resultado = 100 / valor
except (FileNotFoundError, ValueError, ZeroDivisionError) as e:
    print(f"Ocurrió un error: {type(e).__name__}")
    print(f"Descripción: {e}")

Uso práctico en aplicaciones reales

El manejo de excepciones es especialmente útil cuando trabajamos con entrada de usuario, operaciones de archivos o conexiones de red, donde los errores son comunes:

def obtener_edad():
    while True:
        try:
            edad = int(input("¿Cuál es tu edad? "))
            if edad < 0:
                print("La edad no puede ser negativa.")
                continue
            return edad
        except ValueError:
            print("Por favor, introduce un número entero.")

# Uso de la función
edad_usuario = obtener_edad()
print(f"Tu edad es: {edad_usuario}")

En este ejemplo, la función obtener_edad() sigue pidiendo al usuario que introduzca su edad hasta que proporcione un valor válido. Si el usuario introduce algo que no es un número, capturamos la excepción ValueError y le pedimos que lo intente de nuevo.

Buenas prácticas

Al trabajar con excepciones, es importante seguir algunas buenas prácticas:

  1. Ser específico: Captura tipos específicos de excepciones en lugar de usar un bloque except genérico.
  2. Mantener los bloques try pequeños: Incluye solo el código que podría generar la excepción.
  3. No silenciar excepciones: Evita usar except: sin hacer nada con la excepción.
  4. Proporcionar mensajes útiles: Cuando manejes una excepción, proporciona información clara sobre lo que salió mal.
# Mal ejemplo: bloque try demasiado grande
try:
    archivo = open("datos.txt", "r")
    contenido = archivo.read()
    numeros = [int(x) for x in contenido.split()]
    resultado = sum(numeros) / len(numeros)
    print(f"El promedio es: {resultado}")
    archivo.close()
except:
    print("Ocurrió un error")  # Mensaje poco útil

# Buen ejemplo: bloques try específicos
try:
    archivo = open("datos.txt", "r")
except FileNotFoundError:
    print("El archivo 'datos.txt' no existe")
    return

try:
    contenido = archivo.read()
    numeros = [int(x) for x in contenido.split()]
except ValueError:
    print("El archivo contiene datos que no son números")
    archivo.close()
    return

try:
    resultado = sum(numeros) / len(numeros)
    print(f"El promedio es: {resultado}")
except ZeroDivisionError:
    print("El archivo está vacío, no se puede calcular el promedio")

archivo.close()

El manejo de excepciones es una herramienta poderosa que te permite escribir código más robusto que puede manejar situaciones inesperadas de manera elegante. En lugar de que tu programa falle abruptamente, puedes proporcionar una experiencia más amigable para los usuarios y facilitar la depuración de problemas.

Tipos comunes

Python incluye una variedad de excepciones predefinidas que cubren los errores más frecuentes que podemos encontrar durante la ejecución de nuestros programas. Conocer estos tipos de excepciones nos permite manejarlas de forma específica y proporcionar soluciones adecuadas para cada situación.

Excepciones relacionadas con operaciones matemáticas

Las operaciones matemáticas pueden generar varios tipos de errores:

  • ZeroDivisionError: Se produce cuando intentamos dividir un número entre cero.
try:
    resultado = 5 / 0
except ZeroDivisionError:
    print("No es posible dividir entre cero")
  • OverflowError: Ocurre cuando una operación aritmética produce un número demasiado grande para ser representado.
try:
    resultado = 10.0 ** 1000000  # Intentar calcular 10 elevado a un millón
except OverflowError:
    print("El número es demasiado grande para ser representado")

Excepciones relacionadas con tipos de datos

Estas excepciones surgen cuando intentamos realizar operaciones incompatibles con ciertos tipos de datos:

  • TypeError: Se produce cuando una operación o función se aplica a un objeto de tipo inapropiado.
try:
    resultado = "42" + 10  # Intentar sumar un string y un entero
except TypeError:
    print("No se pueden sumar tipos diferentes")
  • ValueError: Ocurre cuando una función recibe un argumento del tipo correcto pero con un valor inapropiado.
try:
    numero = int("abc")  # Intentar convertir una cadena no numérica a entero
except ValueError:
    print("La cadena no representa un número válido")

Excepciones relacionadas con índices y claves

Cuando trabajamos con estructuras de datos como listas o diccionarios:

  • IndexError: Se produce al intentar acceder a un índice que está fuera del rango de una secuencia.
try:
    lista = [1, 2, 3]
    elemento = lista[10]  # Intentar acceder a un índice que no existe
except IndexError:
    print("El índice está fuera del rango de la lista")
  • KeyError: Ocurre cuando intentamos acceder a una clave que no existe en un diccionario.
try:
    diccionario = {"nombre": "Ana", "edad": 25}
    valor = diccionario["telefono"]  # Intentar acceder a una clave inexistente
except KeyError:
    print("La clave 'telefono' no existe en el diccionario")

Excepciones relacionadas con archivos

El manejo de archivos es una fuente común de excepciones:

  • FileNotFoundError: Se produce cuando intentamos abrir un archivo que no existe.
try:
    with open("archivo_inexistente.txt", "r") as archivo:
        contenido = archivo.read()
except FileNotFoundError:
    print("El archivo no existe")
  • PermissionError: Ocurre cuando no tenemos permisos suficientes para acceder a un archivo.
try:
    with open("/etc/passwd", "w") as archivo:  # Intentar escribir en un archivo protegido
        archivo.write("datos")
except PermissionError:
    print("No tienes permisos para modificar este archivo")

Excepciones relacionadas con atributos y nombres

Estas excepciones ocurren cuando intentamos acceder a elementos inexistentes:

  • AttributeError: Se produce al intentar acceder a un atributo o método que no existe.
try:
    texto = "Hola"
    longitud = texto.size  # El método correcto sería len(texto) o texto.__len__()
except AttributeError:
    print("El objeto string no tiene el atributo 'size'")
  • NameError: Ocurre cuando intentamos usar una variable o nombre que no está definido.
try:
    print(variable_no_definida)  # Intentar usar una variable que no existe
except NameError:
    print("La variable no está definida")

Excepciones relacionadas con importaciones

  • ImportError: Se produce cuando falla una importación.
try:
    import biblioteca_inexistente
except ImportError:
    print("No se pudo importar el módulo")
  • ModuleNotFoundError: Es una subclase de ImportError que se produce específicamente cuando no se encuentra el módulo.
try:
    import modulo_que_no_existe
except ModuleNotFoundError:
    print("El módulo no existe")

Jerarquía de excepciones

Las excepciones en Python forman una jerarquía donde todas derivan de la clase base BaseException. La mayoría de las excepciones que manejamos habitualmente derivan de Exception.

Esta jerarquía es importante porque cuando capturamos una excepción, también capturamos todas sus subclases. Por ejemplo, si capturamos Exception, estaremos capturando prácticamente todas las excepciones estándar.

try:
    # Código que podría generar diferentes tipos de excepciones
    resultado = int("abc") / 0
except Exception as e:
    print(f"Se produjo un error: {type(e).__name__}")
    print(f"Descripción: {e}")

Identificando el tipo de excepción

Cuando no estamos seguros de qué excepción podría ocurrir, podemos usar este patrón para identificarla:

try:
    # Código que podría fallar
    resultado = eval(input("Introduce una expresión: "))
except Exception as e:
    print(f"Error de tipo: {type(e).__name__}")
    print(f"Descripción: {e}")

Este enfoque es útil durante el desarrollo para identificar qué excepciones específicas debemos manejar.

Excepciones en bibliotecas externas

Las bibliotecas de terceros suelen definir sus propias excepciones. Por ejemplo, al trabajar con solicitudes HTTP usando la biblioteca requests:

import requests

try:
    respuesta = requests.get("https://api.ejemplo.com/datos", timeout=1)
    respuesta.raise_for_status()  # Lanza una excepción si el código de estado HTTP es un error
except requests.exceptions.ConnectionError:
    print("No se pudo conectar al servidor")
except requests.exceptions.Timeout:
    print("La solicitud excedió el tiempo de espera")
except requests.exceptions.HTTPError as e:
    print(f"Error HTTP: {e}")

Conocer los tipos comunes de excepciones nos permite escribir código más robusto que puede manejar adecuadamente diferentes situaciones de error, mejorando la experiencia del usuario y facilitando la depuración de problemas.

Else y finally

Cuando trabajamos con excepciones en Python, además de los bloques try y except, disponemos de dos cláusulas adicionales que nos permiten controlar con mayor precisión el flujo de ejecución: else y finally. Estas cláusulas complementan el manejo básico de excepciones y nos ayudan a escribir código más limpio y estructurado.

La cláusula else

La cláusula else en un bloque try-except se ejecuta únicamente cuando no ocurre ninguna excepción en el bloque try. Podemos pensar en ella como el código que se ejecuta cuando todo sale bien.

try:
    numero = int(input("Introduce un número: "))
    resultado = 100 / numero
except ValueError:
    print("Debes introducir un número válido.")
except ZeroDivisionError:
    print("No puedes dividir entre cero.")
else:
    print(f"El resultado es: {resultado}")
    # Este código solo se ejecuta si no hubo excepciones

En este ejemplo, el mensaje con el resultado solo se mostrará si la conversión a entero y la división se realizan correctamente, sin generar ninguna excepción.

La cláusula else resulta especialmente útil para separar el código que podría fallar del código que depende de su éxito. Esto hace que nuestro programa sea más claro y fácil de mantener.

Casos de uso prácticos para else

Un patrón común es utilizar else para operaciones que solo deben realizarse si las operaciones anteriores tuvieron éxito:

try:
    archivo = open("datos.txt", "r")
    contenido = archivo.read()
except FileNotFoundError:
    print("El archivo no existe.")
    contenido = ""
else:
    print("Archivo leído correctamente.")
    archivo.close()  # Solo cerramos si se abrió con éxito

También es útil cuando queremos realizar varias operaciones relacionadas y solo continuar si todas tienen éxito:

try:
    datos = obtener_datos_de_api()
    validar_formato(datos)
except ConexionError:
    print("No se pudo conectar con el servidor.")
except FormatoInvalidoError:
    print("Los datos recibidos tienen un formato incorrecto.")
else:
    # Solo procesamos si obtuvimos y validamos los datos correctamente
    resultados = procesar_datos(datos)
    guardar_resultados(resultados)

La cláusula finally

La cláusula finally contiene código que se ejecuta siempre, independientemente de si ocurrió una excepción o no. Es ideal para tareas de limpieza que deben realizarse en cualquier caso, como cerrar archivos o conexiones.

try:
    archivo = open("registro.txt", "w")
    archivo.write("Operación iniciada\n")
    # Código que podría generar una excepción
    resultado = 10 / int(input("Introduce un número: "))
    archivo.write(f"Resultado: {resultado}\n")
except ZeroDivisionError:
    archivo.write("Error: División por cero\n")
except ValueError:
    archivo.write("Error: Valor no válido\n")
finally:
    archivo.write("Operación finalizada\n")
    archivo.close()  # El archivo se cierra siempre
    print("Proceso completado")

En este ejemplo, independientemente de si la operación tiene éxito o genera una excepción, el archivo se cerrará correctamente y se mostrará el mensaje "Proceso completado".

Casos de uso prácticos para finally

La cláusula finally es especialmente útil para:

  • Liberar recursos: Cerrar archivos, conexiones de red o bases de datos.
conexion = None
try:
    conexion = conectar_a_base_de_datos()
    datos = conexion.ejecutar_consulta("SELECT * FROM usuarios")
    procesar_datos(datos)
except ConexionError:
    print("Error al conectar con la base de datos")
except ConsultaError:
    print("Error al ejecutar la consulta")
finally:
    if conexion:
        conexion.cerrar()  # La conexión se cierra siempre
  • Restaurar estados: Devolver sistemas a su estado original después de operaciones.
modo_original = sistema.obtener_modo()
try:
    sistema.cambiar_modo("mantenimiento")
    realizar_actualizacion()
except ActualizacionError:
    print("La actualización falló")
finally:
    sistema.cambiar_modo(modo_original)  # Restauramos el modo original
  • Registrar finalización: Registrar que un proceso ha terminado, independientemente del resultado.
try:
    registrar_inicio("tarea_diaria")
    ejecutar_tarea_diaria()
except Exception as e:
    registrar_error("tarea_diaria", str(e))
finally:
    registrar_finalizacion("tarea_diaria")  # Siempre registramos que terminó

Combinando else y finally

Podemos usar ambas cláusulas en el mismo bloque try-except para obtener un control aún más preciso:

try:
    archivo = open("datos.txt", "r")
    contenido = archivo.read()
except FileNotFoundError:
    print("El archivo no existe, se creará uno nuevo.")
    archivo = open("datos.txt", "w")
    archivo.write("Archivo creado automáticamente")
else:
    print(f"Contenido leído: {contenido}")
    # Este código solo se ejecuta si no hubo excepciones
finally:
    print("Operación de archivo completada.")
    archivo.close()  # El archivo se cierra siempre, se haya abierto para leer o escribir

En este ejemplo:

  1. Si el archivo existe, se lee su contenido
  2. Si no existe, se captura la excepción y se crea un nuevo archivo
  3. La cláusula else solo se ejecuta si el archivo existía y se leyó correctamente
  4. La cláusula finally se ejecuta siempre, cerrando el archivo

Orden de ejecución

Es importante entender el orden de ejecución de estas cláusulas:

  1. El código en el bloque try se ejecuta primero
  2. Si ocurre una excepción, se ejecuta el bloque except correspondiente
  3. Si no ocurre ninguna excepción, se ejecuta el bloque else
  4. El bloque finally se ejecuta siempre, al final
def demostrar_orden():
    try:
        print("1. Ejecutando bloque try")
        # Descomentar para generar una excepción:
        # x = 1 / 0
    except ZeroDivisionError:
        print("2. Ejecutando bloque except")
    else:
        print("3. Ejecutando bloque else")
    finally:
        print("4. Ejecutando bloque finally")
    
    print("5. Continuando después del bloque try")

demostrar_orden()

Consideraciones importantes

  • Return en bloques try/except/else/finally: Si hay una sentencia return en cualquiera de estos bloques, el bloque finally se ejecutará antes de que el valor sea devuelto.
def dividir(a, b):
    try:
        resultado = a / b
        return resultado  # Este return no se ejecuta inmediatamente
    except ZeroDivisionError:
        print("Error: División por cero")
        return None  # Este return tampoco se ejecuta inmediatamente
    finally:
        print("División finalizada")  # Esto se ejecuta antes de cualquier return
        # Ahora sí se devuelve el valor correspondiente

print(dividir(10, 2))  # Imprime "División finalizada" y luego 5.0
print(dividir(10, 0))  # Imprime "Error: División por cero", "División finalizada" y luego None
  • Excepciones en finally: Si se produce una excepción en el bloque finally, esta reemplazará a cualquier excepción anterior que se hubiera producido.
try:
    1 / 0  # Genera ZeroDivisionError
except ZeroDivisionError:
    print("Capturada división por cero")
    # La excepción ha sido manejada
finally:
    # Si descomentas la siguiente línea, el ZeroDivisionError original se perderá
    # y será reemplazado por este ValueError
    # int("abc")  # Genera ValueError
    print("Bloque finally ejecutado")

Las cláusulas else y finally nos permiten estructurar nuestro código de manejo de excepciones de manera más clara y robusta, separando el flujo normal de ejecución de las tareas de limpieza y recuperación. Utilizadas correctamente, estas cláusulas nos ayudan a escribir programas más resilientes y fáciles de mantener.

Lanzar excepciones

Hasta ahora hemos visto cómo manejar excepciones que ocurren durante la ejecución de nuestro código, pero Python también nos permite lanzar nuestras propias excepciones de forma deliberada. Esta capacidad es fundamental cuando desarrollamos funciones o bibliotecas que necesitan comunicar condiciones de error a quien las utiliza.

Lanzar excepciones es como activar una alarma cuando detectamos que algo no está bien en nuestro programa. En lugar de continuar con una operación que sabemos que fallará más adelante, podemos detenerla inmediatamente y proporcionar información clara sobre el problema.

Usando la instrucción raise

La forma más básica de lanzar una excepción es mediante la instrucción raise, seguida del tipo de excepción que queremos generar:

def dividir(a, b):
    if b == 0:
        raise ZeroDivisionError("No se puede dividir entre cero")
    return a / b

try:
    resultado = dividir(10, 0)
except ZeroDivisionError as e:
    print(f"Error: {e}")

En este ejemplo, la función dividir verifica si el divisor es cero antes de intentar la división. Si lo es, lanza una excepción ZeroDivisionError con un mensaje personalizado, evitando que Python tenga que detectar el error por sí mismo.

Cuándo lanzar excepciones

Las excepciones deben lanzarse en situaciones excepcionales, no como parte del flujo normal del programa. Algunos casos apropiados para lanzar excepciones son:

  • Validación de parámetros: Cuando una función recibe argumentos inválidos.
def calcular_raiz_cuadrada(numero):
    if numero < 0:
        raise ValueError("No se puede calcular la raíz cuadrada de un número negativo")
    return numero ** 0.5
  • Estados imposibles: Cuando el programa llega a un estado que no debería ser posible.
def procesar_respuesta(respuesta):
    if respuesta.codigo == 200:
        return respuesta.datos
    elif respuesta.codigo == 404:
        return None
    else:
        raise RuntimeError(f"Código de respuesta no manejado: {respuesta.codigo}")
  • Precondiciones no cumplidas: Cuando no se cumplen las condiciones necesarias para ejecutar una operación.
def retirar_dinero(cuenta, cantidad):
    if not cuenta.esta_activa:
        raise ValueError("La cuenta no está activa")
    
    if cantidad <= 0:
        raise ValueError("La cantidad debe ser positiva")
        
    if cantidad > cuenta.saldo:
        raise ValueError("Saldo insuficiente")
        
    cuenta.saldo -= cantidad
    return cuenta.saldo

Tipos de excepciones comunes para lanzar

Aunque podemos lanzar cualquier tipo de excepción, es recomendable usar el tipo más apropiado según la situación:

  • ValueError: Cuando un argumento tiene el tipo correcto pero un valor inapropiado.
def establecer_edad(edad):
    if not isinstance(edad, int):
        raise TypeError("La edad debe ser un número entero")
    if edad < 0 or edad > 150:
        raise ValueError("La edad debe estar entre 0 y 150 años")
    return edad
  • TypeError: Cuando un argumento es de un tipo incorrecto.
def concatenar(texto, repeticiones):
    if not isinstance(texto, str):
        raise TypeError("El primer argumento debe ser una cadena de texto")
    if not isinstance(repeticiones, int):
        raise TypeError("El segundo argumento debe ser un número entero")
    return texto * repeticiones
  • RuntimeError: Para errores que solo pueden detectarse durante la ejecución.
def conectar_a_servidor():
    if not hay_conexion_internet():
        raise RuntimeError("No hay conexión a Internet")
    # Código para conectar al servidor

Relanzando excepciones

A veces queremos capturar una excepción, realizar alguna acción (como registrar el error) y luego volver a lanzarla para que sea manejada en un nivel superior:

def procesar_archivo(ruta):
    try:
        with open(ruta, 'r') as archivo:
            return archivo.read()
    except FileNotFoundError as e:
        print(f"Registrando error: {e}")
        raise  # Relanza la última excepción

También podemos capturar un tipo de excepción y lanzar otra diferente, manteniendo el contexto original:

def obtener_configuracion(archivo):
    try:
        with open(archivo, 'r') as f:
            return f.read()
    except FileNotFoundError as e:
        raise ConfigurationError(f"Archivo de configuración no encontrado: {archivo}") from e

La cláusula from e establece la excepción original como la "causa" de la nueva excepción, lo que ayuda en la depuración.

Creando excepciones personalizadas

Para aplicaciones más complejas, a menudo es útil definir nuestros propios tipos de excepciones. Esto se hace creando clases que hereden de Exception:

class SaldoInsuficienteError(Exception):
    """Se lanza cuando se intenta retirar más dinero del disponible."""
    
    def __init__(self, saldo, cantidad):
        self.saldo = saldo
        self.cantidad = cantidad
        self.deficit = cantidad - saldo
        mensaje = f"No hay suficiente saldo. Saldo: {saldo}, Cantidad solicitada: {cantidad}"
        super().__init__(mensaje)

def retirar(cuenta, cantidad):
    if cantidad > cuenta.saldo:
        raise SaldoInsuficienteError(cuenta.saldo, cantidad)
    cuenta.saldo -= cantidad
    return cuenta.saldo

Las excepciones personalizadas permiten:

  • Proporcionar información específica sobre el error (como el saldo disponible y la cantidad solicitada)
  • Permitir que el código que las captura identifique exactamente qué tipo de error ocurrió
  • Crear una jerarquía de excepciones para tu aplicación

Buenas prácticas al lanzar excepciones

  • Mensajes claros: Incluye información específica sobre qué salió mal y posiblemente cómo solucionarlo.
# Poco útil
raise ValueError("Fecha inválida")

# Mejor
raise ValueError("La fecha '2023-13-45' no es válida. El formato debe ser YYYY-MM-DD")
  • Excepciones específicas: Usa el tipo de excepción más específico posible para el error.
# Demasiado genérico
if not os.path.exists(ruta):
    raise Exception("Problema con el archivo")

# Mejor
if not os.path.exists(ruta):
    raise FileNotFoundError(f"No se encontró el archivo: {ruta}")
  • Validación temprana: Verifica los parámetros al inicio de la función para fallar rápido.
def procesar_datos(datos):
    # Validación al inicio
    if datos is None:
        raise ValueError("Los datos no pueden ser None")
    if not isinstance(datos, list):
        raise TypeError("Los datos deben ser una lista")
    if len(datos) == 0:
        raise ValueError("La lista de datos no puede estar vacía")
    
    # Procesamiento principal
    resultado = []
    for item in datos:
        # ...
  • Documentación: Documenta qué excepciones puede lanzar tu función y bajo qué circunstancias.
def conectar_base_datos(host, puerto, usuario, contraseña):
    """
    Establece conexión con la base de datos.
    
    Args:
        host (str): Dirección del servidor
        puerto (int): Puerto de conexión
        usuario (str): Nombre de usuario
        contraseña (str): Contraseña de acceso
        
    Returns:
        Conexión a la base de datos
        
    Raises:
        ConnectionError: Si no se puede establecer la conexión
        AuthenticationError: Si las credenciales son incorrectas
        TimeoutError: Si la conexión tarda demasiado tiempo
    """
    # Implementación

Ejemplo práctico: Validación de entrada de usuario

Veamos un ejemplo completo de cómo usar excepciones para validar la entrada del usuario:

def obtener_edad():
    while True:
        try:
            entrada = input("Introduce tu edad: ")
            
            if not entrada.strip():
                raise ValueError("La entrada no puede estar vacía")
                
            edad = int(entrada)
            
            if edad < 0:
                raise ValueError("La edad no puede ser negativa")
                
            if edad > 120:
                raise ValueError("La edad parece demasiado alta")
                
            return edad
            
        except ValueError as e:
            if str(e).startswith("invalid literal for int"):
                print("Por favor, introduce un número válido")
            else:
                print(f"Error: {e}")

# Uso
try:
    edad_usuario = obtener_edad()
    print(f"Tu edad es: {edad_usuario}")
except KeyboardInterrupt:
    print("\nOperación cancelada por el usuario")

Este ejemplo muestra cómo podemos usar excepciones tanto para validar la entrada como para proporcionar mensajes de error específicos, creando una interfaz de usuario más robusta y amigable.

Lanzar excepciones de manera efectiva es una habilidad importante que te permite comunicar claramente los errores y crear código más robusto. Al combinar esta técnica con el manejo adecuado de excepciones, puedes desarrollar programas que respondan elegantemente a situaciones inesperadas.

Aprende Python online

Otros ejercicios de programación de Python

Evalúa tus conocimientos de esta lección Excepciones con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Módulo math

Python
Puzzle

Reto herencia

Python
Código

Excepciones

Python
Test

Introducción a Python

Python
Test

Reto variables

Python
Código

Funciones Python

Python
Puzzle

Reto funciones

Python
Código

Módulo datetime

Python
Test

Reto acumulación

Python
Código

Reto estructuras condicionales

Python
Código

Polimorfismo

Python
Test

Módulo os

Python
Test

Reto métodos dunder

Python
Código

Diccionarios

Python
Puzzle

Reto clases y objetos

Python
Código

Reto operadores

Python
Código

Operadores

Python
Test

Estructuras de control

Python
Puzzle

Funciones lambda

Python
Test

Reto diccionarios

Python
Código

Reto función lambda

Python
Código

Encapsulación

Python
Puzzle

Reto coleciones

Python
Proyecto

Reto funciones auxiliares

Python
Código

Crear módulos y paquetes

Python
Puzzle

Módulo datetime

Python
Puzzle

Excepciones

Python
Puzzle

Operadores

Python
Puzzle

Diccionarios

Python
Test

Reto map, filter

Python
Código

Reto tuplas

Python
Código

Proyecto gestor de tareas CRUD

Python
Proyecto

Tuplas

Python
Puzzle

Variables

Python
Puzzle

Tipos de datos

Python
Puzzle

Conjuntos

Python
Test

Reto mixins

Python
Código

Módulo csv

Python
Test

Módulo json

Python
Test

Herencia

Python
Test

Análisis de datos de ventas con Pandas

Python
Proyecto

Reto fechas y tiempo

Python
Proyecto

Reto estructuras de iteración

Python
Código

Funciones

Python
Test

Reto comprehensions

Python
Código

Variables

Python
Test

Reto serialización

Python
Proyecto

Módulo csv

Python
Puzzle

Reto polimorfismo

Python
Código

Polimorfismo

Python
Puzzle

Clases y objetos

Python
Código

Reto encapsulación

Python
Código

Estructuras de control

Python
Test

Importar módulos y paquetes

Python
Test

Módulo math

Python
Test

Funciones lambda

Python
Puzzle

Reto excepciones

Python
Código

Listas

Python
Puzzle

Reto archivos

Python
Proyecto

Encapsulación

Python
Test

Reto conjuntos

Python
Código

Clases y objetos

Python
Test

Instalación de Python y creación de proyecto

Python
Test

Reto listas

Python
Código

Tipos de datos

Python
Test

Crear módulos y paquetes

Python
Test

Tuplas

Python
Test

Herencia

Python
Puzzle

Reto acceso a sistema

Python
Proyecto

Proyecto sintaxis calculadora

Python
Proyecto

Importar módulos y paquetes

Python
Puzzle

Clases y objetos

Python
Puzzle

Módulo os

Python
Puzzle

Listas

Python
Test

Conjuntos

Python
Puzzle

Reto tipos de datos

Python
Código

Reto matemáticas

Python
Proyecto

Módulo json

Python
Puzzle

Todas las lecciones de Python

Accede a todas las lecciones de Python y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Python

Python

Introducción

Instalación Y Creación De Proyecto

Python

Introducción

Tema 2: Tipos De Datos, Variables Y Operadores

Python

Introducción

Instalación De Python

Python

Introducción

Tipos De Datos

Python

Sintaxis

Variables

Python

Sintaxis

Operadores

Python

Sintaxis

Estructuras De Control

Python

Sintaxis

Funciones

Python

Sintaxis

Estructuras Control Iterativo

Python

Sintaxis

Estructuras Control Condicional

Python

Sintaxis

Testing Con Pytest

Python

Sintaxis

Listas

Python

Estructuras De Datos

Tuplas

Python

Estructuras De Datos

Diccionarios

Python

Estructuras De Datos

Conjuntos

Python

Estructuras De Datos

Comprehensions

Python

Estructuras De Datos

Clases Y Objetos

Python

Programación Orientada A Objetos

Excepciones

Python

Programación Orientada A Objetos

Encapsulación

Python

Programación Orientada A Objetos

Herencia

Python

Programación Orientada A Objetos

Polimorfismo

Python

Programación Orientada A Objetos

Mixins Y Herencia Múltiple

Python

Programación Orientada A Objetos

Métodos Especiales (Dunder Methods)

Python

Programación Orientada A Objetos

Composición De Clases

Python

Programación Orientada A Objetos

Funciones Lambda

Python

Programación Funcional

Aplicación Parcial

Python

Programación Funcional

Entrada Y Salida, Manejo De Archivos

Python

Programación Funcional

Decoradores

Python

Programación Funcional

Generadores

Python

Programación Funcional

Paradigma Funcional

Python

Programación Funcional

Composición De Funciones

Python

Programación Funcional

Funciones Orden Superior Map Y Filter

Python

Programación Funcional

Funciones Auxiliares

Python

Programación Funcional

Reducción Y Acumulación

Python

Programación Funcional

Archivos Comprimidos

Python

Entrada Y Salida Io

Entrada Y Salida Avanzada

Python

Entrada Y Salida Io

Archivos Temporales

Python

Entrada Y Salida Io

Contexto With

Python

Entrada Y Salida Io

Módulo Csv

Python

Biblioteca Estándar

Módulo Json

Python

Biblioteca Estándar

Módulo Datetime

Python

Biblioteca Estándar

Módulo Math

Python

Biblioteca Estándar

Módulo Os

Python

Biblioteca Estándar

Módulo Re

Python

Biblioteca Estándar

Módulo Random

Python

Biblioteca Estándar

Módulo Time

Python

Biblioteca Estándar

Módulo Collections

Python

Biblioteca Estándar

Módulo Sys

Python

Biblioteca Estándar

Módulo Statistics

Python

Biblioteca Estándar

Módulo Pickle

Python

Biblioteca Estándar

Módulo Pathlib

Python

Biblioteca Estándar

Importar Módulos Y Paquetes

Python

Paquetes Y Módulos

Crear Módulos Y Paquetes

Python

Paquetes Y Módulos

Entornos Virtuales (Virtualenv, Venv)

Python

Entorno Y Dependencias

Gestión De Dependencias (Pip, Requirements.txt)

Python

Entorno Y Dependencias

Python-dotenv Y Variables De Entorno

Python

Entorno Y Dependencias

Acceso A Datos Con Mysql, Pymongo Y Pandas

Python

Acceso A Bases De Datos

Acceso A Mongodb Con Pymongo

Python

Acceso A Bases De Datos

Acceso A Mysql Con Mysql Connector

Python

Acceso A Bases De Datos

Novedades Python 3.13

Python

Características Modernas

Operador Walrus

Python

Características Modernas

Pattern Matching

Python

Características Modernas

Instalación Beautiful Soup

Python

Web Scraping

Sintaxis General De Beautiful Soup

Python

Web Scraping

Tipos De Selectores

Python

Web Scraping

Web Scraping De Html

Python

Web Scraping

Web Scraping Para Ciencia De Datos

Python

Web Scraping

Autenticación Y Acceso A Recursos Protegidos

Python

Web Scraping

Combinación De Selenium Con Beautiful Soup

Python

Web Scraping

Accede GRATIS a Python y certifícate

En esta lección

Objetivos de aprendizaje de esta lección

  • Comprender la estructura básica try-except para capturar y manejar excepciones.
  • Identificar y manejar tipos específicos de excepciones comunes en Python.
  • Utilizar las cláusulas else y finally para controlar el flujo de ejecución en bloques try-except.
  • Aprender a lanzar excepciones propias con raise y crear excepciones personalizadas.
  • Aplicar buenas prácticas en el manejo y lanzamiento de excepciones para mejorar la calidad del código.