shelve — Almacenamiento persistente de objetos

Propósito:El módulo shelve implementa el almacenamiento persistente para objetos arbitrarios de Python que pueden ser serializados, usando una interfaz de programación similar a un diccionario.

El módulo shelve puede usarse como una opción simple de almacenamiento persistente para objetos de Python cuando no se requiere una base de datos relacional. Se accede al estante mediante llaves, igual que con un diccionario. Los valores son serializados y se escriben en una base de datos creada. y gestionada por dbm.

Crear un nuevo estante

La forma más simple de usar shelve es a través de la clase DbfilenameShelf. Utiliza dbm para almacenar los datos. La clase puede ser utilizada directamente, o llamando a shelve.open().

shelve_create.py
import shelve

with shelve.open('test_shelf.db') as s:
    s['key1'] = {
        'int': 10,
        'float': 9.5,
        'string': 'Sample data',
    }

Para volver a acceder a los datos, abre el estante y utilízalo como un diccionario.

shelve_existing.py
import shelve

with shelve.open('test_shelf.db') as s:
    existing = s['key1']

print(existing)

La ejecución de ambas secuencias de comandos del ejemplo produce el siguiente resultado.

$ python3 shelve_create.py
$ python3 shelve_existing.py

{'string': 'Sample data', 'int': 10, 'float': 9.5}

El módulo dbm no admite la escritura de múltiples aplicaciones a la misma base de datos al mismo tiempo, pero soporta clientes de solo lectura concurrentes. Si un cliente no va a modificar el estante, dígale a shelve para que abra la base de datos de solo lectura al pasar flag='r'.

shelve_readonly.py
import dbm
import shelve

with shelve.open('test_shelf.db', flag='r') as s:
    print('Existing:', s['key1'])
    try:
        s['key1'] = 'new value'
    except dbm.error as err:
        print('ERROR: {}'.format(err))

Si el programa intenta modificar la base de datos mientras se abre solo para lectura, se genera una excepción de error de acceso. El tipo de excepción depende del módulo de base de datos seleccionado por dbm cuando se creó la base de datos.

$ python3 shelve_readonly.py

Existing: {'string': 'Sample data', 'int': 10, 'float': 9.5}
ERROR: cannot add item to database

Reescritura de datos

Los estantes no rastrean las modificaciones a los objetos volátiles, por defecto. Eso significa que si el contenido de un artículo almacenado en el estante es cambiado, el estante debe actualizarse explícitamente almacenando todo el artículo otra vez.

shelve_withoutwriteback.py
import shelve

with shelve.open('test_shelf.db') as s:
    print(s['key1'])
    s['key1']['new_value'] = 'this was not here before'

with shelve.open('test_shelf.db', writeback=True) as s:
    print(s['key1'])

En este ejemplo, el diccionario en 'key1' no se almacena nuevamente, por lo que cuando el estante se vuelve a abrir, los cambios no se han conservado.

$ python3 shelve_create.py
$ python3 shelve_withoutwriteback.py

{'string': 'Sample data', 'int': 10, 'float': 9.5}
{'string': 'Sample data', 'int': 10, 'float': 9.5}

Para capturar automáticamente los cambios en los objetos volátiles almacenados en el estante, ábrelo con la escritura habilitada. La bandera writeback` causa que el estante recuerde todos los objetos recuperados de la base de datos usando un caché en memoria. Cada objeto de caché también se escribe de nuevo en la base de datos cuando el estante se cierra.

shelve_writeback.py
import shelve
import pprint

with shelve.open('test_shelf.db', writeback=True) as s:
    print('Initial data:')
    pprint.pprint(s['key1'])

    s['key1']['new_value'] = 'this was not here before'
    print('\nModified:')
    pprint.pprint(s['key1'])

with shelve.open('test_shelf.db', writeback=True) as s:
    print('\nPreserved:')
    pprint.pprint(s['key1'])

Aunque reduce la posibilidad de error del programador, y puede hacer La persistencia de objetos más transparente, utilizar el modo de reescritura puede no ser deseable en todas las situaciones. El caché consume memoria extra mientras el estante está abierto y se detiene para escribir todos los objetos almacenados en caché La base de datos cuando se cierra ralentiza la aplicación. Toda la los objetos almacenados en caché se escriben de nuevo en la base de datos porque no hay manera de saber si han sido modificados. Si la aplicación lee más datos de los que escribe, la reescritura afectará el rendimiento innecesariamente.

$ python3 shelve_create.py
$ python3 shelve_writeback.py

Initial data:
{'float': 9.5, 'int': 10, 'string': 'Sample data'}

Modified:
{'float': 9.5,
 'int': 10,
 'new_value': 'this was not here before',
 'string': 'Sample data'}

Preserved:
{'float': 9.5,
 'int': 10,
 'new_value': 'this was not here before',
 'string': 'Sample data'}

Tipos específicos de estantes

Todos los ejemplos anteriores utilizaron la implementación predeterminada del estante. Utilizar shelve.open() en lugar de una de las implementaciones de estantería directamente es un patrón de uso común, especialmente si no importa qué tipo de base de datos se utiliza para almacenar los datos. Hay veces, sin embargo, cuando el formato de la base de datos es importante. En esas situaciones, usa DbfilenameShelf o BsdDbShelf directamente, o incluso hereda de Shelf para una solución personalizada.

Ver también