Python: Acceso a bases de datos

Aprende a conectar y gestionar bases de datos en Python con técnicas CRUD, transacciones y optimización para aplicaciones robustas.

Aprende Python GRATIS y certifícate

Acceso a bases de datos

El acceso a bases de datos representa uno de los pilares fundamentales en el desarrollo de aplicaciones modernas. En Python, la capacidad de interactuar con sistemas de gestión de bases de datos permite crear aplicaciones robustas que pueden almacenar, recuperar y manipular información de manera eficiente.

Fundamentos de la conectividad con bases de datos

Python ofrece múltiples enfoques para trabajar con bases de datos, desde la API estándar DB-API 2.0 hasta bibliotecas especializadas que simplifican las operaciones más comunes. Esta flexibilidad permite a los desarrolladores elegir la herramienta más adecuada según las necesidades específicas del proyecto.

La especificación DB-API 2.0 define una interfaz estándar para módulos de bases de datos en Python. Esta especificación garantiza que diferentes conectores de bases de datos mantengan una sintaxis y comportamiento consistentes, facilitando la portabilidad del código entre diferentes sistemas de gestión de bases de datos.

import sqlite3

# Establecer conexión con la base de datos
conexion = sqlite3.connect('ejemplo.db')
cursor = conexion.cursor()

# Ejecutar una consulta
cursor.execute("SELECT * FROM usuarios WHERE edad > ?", (18,))
resultados = cursor.fetchall()

# Cerrar la conexión
conexion.close()

Tipos de bases de datos y conectores

Python soporta una amplia variedad de sistemas de bases de datos, cada uno con sus propias características y casos de uso específicos. Las bases de datos relacionales como SQLite, PostgreSQL y MySQL siguen siendo las más utilizadas en aplicaciones empresariales.

SQLite se integra nativamente con Python y resulta ideal para aplicaciones pequeñas y medianas, prototipado rápido y desarrollo local. Su naturaleza de archivo único simplifica la distribución y el mantenimiento.

Para bases de datos más robustas, PostgreSQL ofrece características avanzadas como tipos de datos personalizados, índices parciales y soporte completo para transacciones ACID. El conector psycopg2 proporciona una interfaz eficiente y rica en funcionalidades.

import psycopg2

# Configuración de conexión
config = {
    'host': 'localhost',
    'database': 'mi_aplicacion',
    'user': 'usuario',
    'password': 'contraseña'
}

# Establecer conexión
conexion = psycopg2.connect(**config)

Gestión de conexiones y recursos

La gestión adecuada de conexiones constituye un aspecto crítico en el desarrollo de aplicaciones que acceden a bases de datos. Python proporciona mecanismos elegantes para garantizar que los recursos se liberen correctamente, incluso cuando ocurren errores.

El uso de context managers mediante la declaración with asegura que las conexiones se cierren automáticamente al finalizar el bloque de código, independientemente de si la operación se completa exitosamente o genera una excepción.

import sqlite3

# Uso de context manager para gestión automática de recursos
with sqlite3.connect('datos.db') as conexion:
    cursor = conexion.cursor()
    cursor.execute("INSERT INTO productos (nombre, precio) VALUES (?, ?)", 
                   ("Laptop", 999.99))
    conexion.commit()
# La conexión se cierra automáticamente

Operaciones CRUD fundamentales

Las operaciones CRUD (Create, Read, Update, Delete) forman la base de cualquier aplicación que interactúa con bases de datos. Python facilita la implementación de estas operaciones mediante una sintaxis clara y expresiva.

La inserción de datos requiere especial atención al manejo de parámetros para prevenir ataques de inyección SQL. El uso de placeholders parametrizados garantiza que los datos se escapen correctamente.

def crear_usuario(conexion, nombre, email, edad):
    """Inserta un nuevo usuario en la base de datos"""
    cursor = conexion.cursor()
    query = "INSERT INTO usuarios (nombre, email, edad) VALUES (?, ?, ?)"
    cursor.execute(query, (nombre, email, edad))
    conexion.commit()
    return cursor.lastrowid

Las consultas de lectura pueden optimizarse mediante el uso de métodos específicos como fetchone(), fetchmany() y fetchall(), dependiendo de la cantidad de datos esperados y los requisitos de memoria de la aplicación.

def obtener_usuarios_por_edad(conexion, edad_minima):
    """Recupera usuarios que superan una edad específica"""
    cursor = conexion.cursor()
    cursor.execute("SELECT id, nombre, email FROM usuarios WHERE edad >= ?", 
                   (edad_minima,))
    return cursor.fetchall()

Manejo de transacciones

Las transacciones garantizan la integridad de los datos mediante el principio de atomicidad: todas las operaciones dentro de una transacción se ejecutan completamente o no se ejecutan en absoluto. Python proporciona control granular sobre las transacciones a través de los métodos commit() y rollback().

def transferir_fondos(conexion, cuenta_origen, cuenta_destino, cantidad):
    """Realiza una transferencia de fondos entre cuentas"""
    try:
        cursor = conexion.cursor()
        
        # Debitar de la cuenta origen
        cursor.execute("UPDATE cuentas SET saldo = saldo - ? WHERE id = ?", 
                       (cantidad, cuenta_origen))
        
        # Acreditar a la cuenta destino
        cursor.execute("UPDATE cuentas SET saldo = saldo + ? WHERE id = ?", 
                       (cantidad, cuenta_destino))
        
        # Confirmar la transacción
        conexion.commit()
        
    except Exception as error:
        # Revertir cambios en caso de error
        conexion.rollback()
        raise error

Optimización y mejores prácticas

La optimización del acceso a bases de datos implica considerar aspectos como el pooling de conexiones, la preparación de statements y el uso eficiente de índices. Python ofrece bibliotecas especializadas que implementan estas optimizaciones de manera transparente.

El pooling de conexiones reduce la sobrecarga asociada con el establecimiento y cierre frecuente de conexiones, especialmente importante en aplicaciones web con alta concurrencia.

from sqlalchemy import create_engine
from sqlalchemy.pool import QueuePool

# Configurar pool de conexiones
engine = create_engine(
    'postgresql://usuario:password@localhost/basedatos',
    poolclass=QueuePool,
    pool_size=10,
    max_overflow=20
)

La validación de datos antes de las operaciones de base de datos previene errores y mejora la experiencia del usuario. Python permite implementar validaciones robustas que se ejecutan antes de interactuar con la base de datos.

def validar_email(email):
    """Valida formato de email antes de insertar en base de datos"""
    import re
    patron = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return re.match(patron, email) is not None

def crear_usuario_validado(conexion, nombre, email, edad):
    """Crea usuario con validaciones previas"""
    if not validar_email(email):
        raise ValueError("Formato de email inválido")
    
    if edad < 0 or edad > 150:
        raise ValueError("Edad fuera del rango válido")
    
    return crear_usuario(conexion, nombre, email, edad)
Empezar curso de Python

Lecciones de este módulo de Python

Lecciones de programación del módulo Acceso a bases de datos del curso de Python.