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) |
A partire dal 1 gennaio 2021 le versioni 2.x di Python non sono piu' supportate. Ti invito a consultare la corrispondente versione 3.x dell'articolo per il modulo shelve
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 .
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.
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'}
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: