Buscar..


Introducción

Shelve es un módulo de Python que se utiliza para almacenar objetos en un archivo. El módulo de almacenamiento implementa el almacenamiento persistente para objetos Python arbitrarios que pueden ser decapados, utilizando una API similar a un diccionario. El módulo de almacenamiento puede usarse como una opción de almacenamiento persistente simple para objetos de Python cuando una base de datos relacional es excesiva. Se accede a la estantería mediante llaves, igual que con un diccionario. Los valores se decapan y se escriben en una base de datos creada y administrada por anydbm.

Observaciones

Nota: No confíe en que el estante se cierre automáticamente; siempre llame a close() explícitamente cuando ya no lo necesite más, o use shelve.open() como administrador de contexto:

with shelve.open('spam') as db:
    db['eggs'] = 'eggs'

Advertencia:

Debido a que la shelve módulo está respaldado por pickle , es inseguro para cargar un estante de una fuente no fiable. Al igual que con Pickle, cargar un estante puede ejecutar código arbitrario.

Restricciones

1 . La elección del paquete de base de datos que se utilizará (como dbm.ndbm o dbm.gnu) depende de la interfaz disponible. Por lo tanto, no es seguro abrir la base de datos directamente usando dbm. La base de datos también está (desafortunadamente) sujeta a las limitaciones de dbm, si se usa; esto significa que (la representación en escabeche) de los objetos almacenados en la base de datos debería ser bastante pequeña, y en casos raros, las colisiones de claves pueden hacer que la base de datos rechazar actualizaciones.

2. El módulo de archivado no admite el acceso simultáneo de lectura / escritura a objetos archivados. (Múltiples accesos de lectura simultáneos son seguros.) Cuando un programa tiene un estante abierto para escribir, ningún otro programa debería tenerlo abierto para leer o escribir. El bloqueo de archivos de Unix se puede usar para resolver esto, pero esto difiere entre las versiones de Unix y requiere conocimiento sobre la implementación de la base de datos utilizada.

Código de muestra para estantería

Para archivar un objeto, primero importe el módulo y luego asigne el valor del objeto de la siguiente manera:

import shelve 
 database = shelve.open(filename.suffix) 
 object = Object() 
 database['key'] = object 

Para resumir la interfaz (la clave es una cadena, los datos son un objeto arbitrario):

import shelve

d = shelve.open(filename)  # open -- file may get suffix added by low-level
                           # library

d[key] = data              # store data at key (overwrites old data if
                           # using an existing key)
data = d[key]              # retrieve a COPY of data at key (raise KeyError
                           # if no such key)
del d[key]                 # delete data stored at key (raises KeyError
                           # if no such key)

flag = key in d            # true if the key exists
klist = list(d.keys())     # a list of all existing keys (slow!)

# as d was opened WITHOUT writeback=True, beware:
d['xx'] = [0, 1, 2]        # this works as expected, but...
d['xx'].append(3)          # *this doesn't!* -- d['xx'] is STILL [0, 1, 2]!

# having opened d without writeback=True, you need to code carefully:
temp = d['xx']             # extracts the copy
temp.append(5)             # mutates the copy
d['xx'] = temp             # stores the copy right back, to persist it

# or, d=shelve.open(filename,writeback=True) would let you just code
# d['xx'].append(5) and have it work as expected, BUT it would also
# consume more memory and make the d.close() operation slower.

d.close()                  # close it

Creando un nuevo estante

La forma más sencilla de usar shelve es a través de la clase DbfilenameShelf . Utiliza anydbm para almacenar los datos. Puede usar la clase directamente, o simplemente llamar a shelve.open () :

import shelve

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

Para volver a acceder a los datos, abra el estante y utilícelo como un diccionario:

    import shelve
    
    s = shelve.open('test_shelf.db')
    try:
        existing = s['key1']
    finally:
        s.close()

print existing

Si ejecuta ambos scripts de muestra, debería ver:

$ python shelve_create.py
$ python shelve_existing.py

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

El módulo dbm no admite múltiples aplicaciones que escriban en la misma base de datos al mismo tiempo. Si sabe que su cliente no modificará el estante, puede pedirle a la estantería que abra la base de datos de solo lectura.

import shelve

s = shelve.open('test_shelf.db', flag='r')
try:
    existing = s['key1']
finally:
    s.close()

print existing

Si su 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 anydbm cuando se creó la base de datos.

Respóndeme

Los estantes no rastrean las modificaciones a objetos volátiles, por defecto. Eso significa que si cambia el contenido de un elemento almacenado en el estante, debe actualizar el estante explícitamente almacenándolo nuevamente.

import shelve

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

s = shelve.open('test_shelf.db', writeback=True)
try:
    print s['key1']
finally:
    s.close()

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

$ python shelve_create.py
$ python shelve_withoutwriteback.py

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

Para capturar automáticamente los cambios en los objetos volátiles almacenados en el estante, abra el estante con la función de escritura habilitada. El indicador de reescritura hace que el estante recuerde todos los objetos recuperados de la base de datos utilizando un caché en memoria. Cada objeto de caché también se vuelve a escribir en la base de datos cuando se cierra el estante.

import shelve

s = shelve.open('test_shelf.db', writeback=True)
try:
    print s['key1']
    s['key1']['new_value'] = 'this was not here before'
    print s['key1']
finally:
    s.close()

s = shelve.open('test_shelf.db', writeback=True)
try:
    print s['key1']
finally:
    s.close()

Aunque reduce la posibilidad de error del programador y puede hacer que la persistencia del objeto sea más transparente, el uso del modo de reescritura puede no ser deseable en todas las situaciones. La memoria caché consume memoria adicional mientras el estante está abierto, y hacer una pausa para escribir cada objeto almacenado en caché de nuevo en la base de datos cuando se cierra puede llevar más tiempo. Dado que no hay forma de saber si los objetos almacenados en caché se han modificado, todos se han vuelto a escribir. Si su aplicación lee datos más de lo que escribe, la respuesta por escrito agregará más sobrecarga de la que podría desear.

$ python shelve_create.py
$ python shelve_writeback.py

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


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow