shelve en Python: persistencia simple

Publicado el: 01/08/2026
Tempo de leitura: 5 minutos
Base de datos local que representa persistencia con shelve en Python

El módulo shelve permite guardar objetos Python en un archivo persistente con una interfaz parecida a un diccionario. Es útil cuando un script necesita conservar una pequeña cantidad de estado entre ejecuciones sin instalar un servidor de base de datos. Su sencillez no elimina los riesgos relacionados con seguridad, portabilidad, concurrencia y mantenimiento.

Cuándo conviene usar shelve

Utiliza shelve en scripts locales, prototipos, utilidades de línea de comandos, cachés pequeñas, automatizaciones personales y herramientas de escritorio. Puedes abrir una estantería, asignar valores a claves de texto y cerrarla. Para aplicaciones web, varios procesos, consultas complejas o datos críticos, es mejor elegir SQLite, PostgreSQL u otra base transaccional.

Ejemplo básico

import shelve

with shelve.open("datos_app") as db:
    db["usuario"] = {"nombre": "Ana", "nivel": 3}
    db["tema"] = "oscuro"

with shelve.open("datos_app") as db:
    print(db["usuario"])

El bloque with garantiza el cierre incluso si ocurre una excepción. Según el sistema operativo y la implementación dbm, una sola base lógica puede producir varios archivos con extensiones diferentes. Considera el nombre enviado a open como una base y no como la garantía de un único archivo.

Funcionamiento interno

shelve combina una base clave-valor de la familia dbm con la serialización de objetos mediante pickle. Las claves son cadenas. Los valores pueden ser listas, diccionarios, tuplas, instancias de clases y otros objetos serializables. Esta flexibilidad es cómoda, pero los datos no son legibles como JSON y nunca deben cargarse desde una fuente no confiable.

Actualización de valores mutables

Un error frecuente consiste en recuperar una lista o un diccionario, modificarlo y esperar que el cambio se guarde automáticamente. El patrón más seguro es volver a asignar el objeto modificado.

with shelve.open("datos_app") as db:
    perfil = db["usuario"]
    perfil["nivel"] += 1
    db["usuario"] = perfil

La opción writeback=True mantiene en caché los objetos consultados y los escribe al cerrar. Puede simplificar el código, pero aumenta el consumo de memoria y puede hacer que el cierre tarde mucho.

with shelve.open("datos_app", writeback=True) as db:
    db["usuario"]["nivel"] += 1

Usa writeback solamente con conjuntos pequeños y después de comprender su coste. La reasignación explícita suele ser más predecible.

Operaciones disponibles

Una estantería admite métodos conocidos como keys(), values(), items(), get() y pop(), además del operador in. Recorrer todos los valores puede ser costoso porque cada elemento necesita deserialización.

with shelve.open("datos_app") as db:
    db["contador"] = db.get("contador", 0) + 1
    if "configuracion" in db:
        print(db["configuracion"])
    for clave in db.keys():
        print(clave)

Modos de apertura

El argumento flag controla la apertura. El valor predeterminado c permite lectura y escritura y crea la base cuando no existe. r abre una base existente en modo de solo lectura. w abre una base existente para leer y escribir. n crea una base vacía y reemplaza la anterior.

Prefiere r en procesos que solo consultan información. Usa n únicamente para reconstrucciones deliberadas, pruebas aisladas o comandos de reinicio.

Reglas de seguridad

Nunca abras una estantería enviada por un usuario, descargada de internet, recibida por correo o modificada por una cuenta no confiable. Los datos pickle pueden ejecutar código durante la carga. Mantén los archivos en un directorio controlado, con permisos restrictivos y fuera de carpetas públicas.

shelve tampoco cifra los valores. Contraseñas, tokens, claves privadas y credenciales de API deben guardarse en un gestor de secretos o en otro sistema protegido.

Concurrencia e integridad

El módulo no ofrece un bloqueo portátil para varios escritores. Dos procesos escribiendo en la misma base pueden corromperla. La regla segura es permitir un solo escritor. Si varios procesos o máquinas necesitan compartir los datos, utiliza SQLite con transacciones o un servicio de base de datos diseñado para concurrencia.

Un cierre brusco o una pérdida de energía también puede dejar archivos inconsistentes. Realiza copias de seguridad, prueba la restauración y considera escribir cambios en una base temporal antes de sustituir la principal.

Portabilidad y migraciones

La implementación dbm cambia entre sistemas operativos e instalaciones. Los archivos creados en un equipo pueden no abrirse en otro. Los objetos pickle dependen además de rutas de módulos y definiciones de clases compatibles. Renombrar o mover una clase puede impedir la lectura de datos antiguos.

Para información que debe durar años, viajar entre plataformas o ser consumida por otros lenguajes, usa JSON, CSV, SQLite o un esquema documentado. shelve funciona mejor como persistencia local controlada.

Un repositorio sencillo

from pathlib import Path
import shelve

class Repositorio:
    def __init__(self, ruta: Path):
        self.ruta = str(ruta)

    def guardar(self, clave: str, valor) -> None:
        with shelve.open(self.ruta) as db:
            db[clave] = valor

    def obtener(self, clave: str, predeterminado=None):
        with shelve.open(self.ruta) as db:
            return db.get(clave, predeterminado)

    def eliminar(self, clave: str) -> bool:
        with shelve.open(self.ruta) as db:
            if clave not in db:
                return False
            del db[clave]
            return True

Encapsular el almacenamiento centraliza rutas, validación, registros y copias de seguridad. También facilita una futura migración a SQLite, porque el resto de la aplicación depende de tu interfaz y no de llamadas dispersas a shelve.

Pruebas seguras

En las pruebas, utiliza tempfile.TemporaryDirectory para obtener almacenamiento aislado y limpieza automática.

from pathlib import Path
from tempfile import TemporaryDirectory

with TemporaryDirectory() as carpeta:
    repo = Repositorio(Path(carpeta) / "prueba")
    repo.guardar("x", {"valor": 10})
    assert repo.obtener("x")["valor"] == 10

Buenas prácticas operativas

Usa claves estables y documentadas. Valida valores antes de escribir. Cierra siempre con with. Evita writeback para colecciones grandes. Mantén un único escritor. Añade copias de seguridad para datos valiosos. Incluye una exportación a JSON y comprueba que puede restaurarse en otra máquina.

Alternativas

JSON es mejor para datos simples y portables. SQLite aporta transacciones, consultas, índices y acceso concurrente más seguro. dbm guarda bytes y deja la serialización a la aplicación. SQLModel y SQLAlchemy son opciones cuando aumentan el dominio y las consultas.

Conclusión

shelve es un puente práctico entre un diccionario temporal y una base completa. Reduce código en proyectos locales pequeños, pero no debe convertirse en una dependencia crítica invisible. Úsalo solo con archivos confiables, comprende los riesgos de pickle, limita la concurrencia y planifica una migración cuando la durabilidad o la escala sean importantes.

Continúa con zipfile en Python, tempfile en Python, tomllib en Python y copy en Python. Consulta la documentación de shelve y la advertencia de seguridad de pickle.

Antes de adoptar el módulo, documenta qué datos se guardarán, durante cuánto tiempo y cómo se recuperarán ante un fallo. Esta decisión evita que un prototipo termine convertido en una dependencia de producción sin supervisión.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Documento y bandeja de entrada que representan buzones de correo con mailbox en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    mailbox en Python: buzones de correo

    Aprende mailbox en Python para leer, crear y migrar Maildir, mbox y MH con locking, flags, mensajes y manejo seguro

    Ler mais

    Tempo de leitura: 5 minutos
    12/08/2026
    Editor de texto que representa formato con textwrap en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    textwrap en Python: formatea textos

    Aprende textwrap en Python para dividir, rellenar, acortar, indentar y quitar sangrías con control de ancho, espacios y palabras largas.

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Carpeta y lupa que representan filtros de nombres con fnmatch en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    fnmatch en Python: filtra nombres de archivos

    Aprende fnmatch en Python para filtrar nombres de archivos con comodines, controlar mayúsculas, excluir patrones y distinguir glob de regex.

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Monitor con datos binarios que representa arrays numéricos compactos en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    array en Python: números compactos

    Aprende array en Python para almacenar números compactos, usar archivos binarios, byte order, memoryview y buffers seguros.

    Ler mais

    Tempo de leitura: 5 minutos
    10/08/2026
    Círculo cromático que representa conversiones RGB, HSV y HLS con colorsys en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    colorsys en Python: RGB, HSV y HLS

    Aprende colorsys en Python para convertir colores entre RGB, HSV, HLS y YIQ, crear paletas y evitar errores de escala

    Ler mais

    Tempo de leitura: 5 minutos
    09/08/2026
    Icono de configuración que representa archivos plist con plistlib en Python
    Bibliotecas y Módulos
    Foto de perfil de Leandro Hirt da Academify

    plistlib: lee y escribe archivos plist

    Aprende plistlib en Python para leer y escribir archivos plist XML y binarios, validar datos y manejar fechas, bytes y

    Ler mais

    Tempo de leitura: 6 minutos
    08/08/2026