shelve - Persistenza di oggetti arbitrari Python

Scopo Il modulo shelve implementa una conservazione persistente di oggetti arbitrari Python i quali possono essere gestiti da pickle, usando una API tipo dizionario.
Versione Python 1.4 e superiore (modificata dalla 2.3)

Il modulo shelve può essere usato come una semplice opzione per una conservazione persistente di oggetti Python, qualora un database relazionale sia eccessivo. Allo shelf si accede tramite chiavi, proprio come un dizionario. I valori vengono passati a pickle, quindi scritti in un database creato e gestito da anydbm.

Creare Un Nuovo Shelf

Il modo più semplice di usare shelve è tramite la classe DbfilenameShelf. Essa usa anydbm per conservare i dati. Si può usare la classe direttamente, oppure chiamare semplicemente shelve.open():

import shelve

s = shelve.open('test_shelf.db')
try:
    s['chiave1'] = { 'int': 10, 'float':9.5, 'string':'Dati di esempio' }
finally:
    s.close()

Per accedere nuovamente ai dati, si apre lo shelf e lo si utilizza come un dizionario:

import shelve

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

print existing

Se si eseguono entrambi gli script di esempio si dovrebbe vedere:

$ python shelve_create.py
$ python shelve_existing.py
{'int': 10, 'float': 9.5, 'string': 'Dati di esempio'}

Il modulo dbm non supporta la scrittura di applicazioni multiple verso lo stesso database allo stesso tempo. Se si sa che un client non modificherà lo shelf, allora si può dire a shelve di aprire il database in sola lettura.

import shelve

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

print existing

Se il proprio programma tenta di modificare il database mentre è aperto in sola lettura, viene generata una eccezione di errore di accesso. Il tipo di eccezione dipende dal modulo di database selezionato da anydbm quando viene creato il database.

Ri-Scrittura

Shelve non mantiene traccia di modifiche ad oggetti volatili, nel modo predefinito. Questo significa che si modifica il contenuto di un elemento contenuto nello shelf, occorre aggiornare esplicitamente lo shelf salvando nuovamente l'elemento.

import shelve

s = shelve.open('test_shelf.db')
try:
    print s['chiave1']
    s['chiave1']['nuovo_valore'] = 'questo prima non era qui'
finally:
    s.close()

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

In questo esempio, il dizionario in 'chiave1' non è stato ancora salvato, quindi quando lo shelf viene riaperto, le modifiche non sono preservate.

$ python shelve_withoutwriteback.py
{'int': 10, 'float': 9.5, 'string': 'Dati di esempio'}
{'int': 10, 'float': 9.5, 'string': 'Dati di esempio'}

Per catturare automaticamente le modifiche agli oggetti volatili conservati nello shelf, si apre lo shelf con abilitato writeback. Il flag writeback fa sì che shelf ricordi tutti gli oggetti che ha recuperato dal database usando una cache di memoria. Ogni oggetto nella cache viene riscritto nel database quando viene chiuso lo shelf.

import shelve

s = shelve.open('test_shelf.db', writeback=True)
try:
    print s['chiave1']
    s['chiave1']['altro_valore'] = 'questo prima non era qui'
    print s['chiave1']
finally:
    s.close()

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

Sebbene vengano ridotte le possibilità di un errore del programmatore e possa rendere la persistenza degli oggetti più trasparente, l'uso di writeback potrebbe non essere conveniente in tutte le situazioni. La cache consuma memoria extra mentre lo shelf è aperto, e la pausa per riscrivere ogni oggetto nella cache nel database quando viene chiuso può richiedere tempo supplementare. Visto che non vi è modo per conoscere se gli oggetti nella cache sono stati modificati, essi vengono tutti riscritti. Se la propria applicazione legge dati più di quanto li scriva, writeback potrebbe appesantire le cose più di quanto non si voglia.

$ python shelve_create.py
$ python shelve_writeback.py
{'int': 10, 'float': 9.5, 'string': 'Dati di esempio'}
{'int': 10, 'float': 9.5, 'altro_valore': 'questo prima non era qui', 'string': 'Dati di esempio'}
{'int': 10, 'float': 9.5, 'altro_valore': 'questo prima non era qui', 'string': 'Dati di esempio'}

Tipi di Shelf Specifici

Gli esempi di cui sopra usano tutti l'implementazione shelf predefinita. Usando shelve.open() invece che una delle implementazioni di shelf direttamente è un modello d'uso comune, specialmene se non ci si deve preoccupare di quale tipo di database venga usato per salvare i dati. Ci sono volte, comunque, in qui occorre conoscere quale tipo di database usare. In queste situazioni si puà usare DbfilenameShelf oppure BsdDbShelf direttamente od addirittura derivare da Shelf per una soluzione personalizzata.

Vedere anche:

shelve
La documentazione della libreria standard per questo modulo.
anydbm
Il modulo anydbm
feedcache
Il modulo feedcache usa shelve come opzione di conservazione predefinita
shove
Shove implenta una API simile con molti formati backend
Persistenza e scambio dati
Altri meccanismi per conservare dati usando i moduli della libreria standard.