shelve - Conservazione Persistente di Oggetti
Scopo: Implementa la conservazione persistente per oggetti Python arbitrari che possono essere preservati usando una API tipo dizionario.
Il modulo shelve può essere usato come semplice opzione di conservazione di oggetti Python quando non è richiesto un database relazionale. L'accesso avviene tramite chiavi, proprio come un dizionario. I valori sono serializzati con pickle e scritti in un database creato e gestito da dbm.
Creare un Nuovo Shelf
Il modo più semplice di usare shelve è tramite la classe DbfilenameShelf
. Usa dbm per conservare i dati. Questa classe può essere usata direttamente oppure chiamando shelve.open()
. Si intende per shelf il nuovo file creato con questa tecnica (n.d.t.).
# shelve_create.py
import shelve
with shelve.open('test_shelf.db') as s:
s['key1'] = {
'int': 10,
'float': 9.5,
'string': 'Dati di esempio',
}
Per accedere nuovamente ai dati, si apra lo shelf e lo si utilizzi come un dizionario.
# shelve_existing.py
import shelve
with shelve.open('test_shelf.db') as s:
existing = s['key1']
print(existing)
L'esecuzione di entrambi gli script di esempio produce il seguente risultato:
$ python3 shelve_create.py $ python3 shelve_existing.py {'int': 10, 'float': 9.5, 'string': 'Dati di esempio'}
Il modulo dbm non supporta la scrittura contemporanea allo stesso database da parte di applicazioni multiple, ma supporta la concorrenza per client a sola lettura. Se un client non modificherà lo shelf, si passi a shelve
l'argomento flag='r'
per aprire il database in sola lettura.
# shelve_readonly.py
import dbm
import shelve
with shelve.open('test_shelf.db', flag='r') as s:
print('Esistente:', s['key1'])
try:
s['key1'] = 'nuovo valore'
except dbm.error as err:
print('ERRORE: {}'.format(err))
Se il programma tenta di modificare il database mentre è aperto in sola lettura, viene generata una eccezione. Il tipo di eccezione dipende dal modulo di database selezionato da dbm quando viene creato il database.
$ python3 shelve_readonly.py Esistente: {'int': 10, 'float': 9.5, 'string': 'Dati di esempio', 'nuovo_valore': 'questo non esisteva prima'} ERRORE: Reader can't store
Riscrittura
shelve non tiene traccia di modifiche a oggetti volatili, nella modalità predefinita. Il che significa che se il contenuto di un elemento conservato nello shelf è cambiato, occorre eseguire esplicitamente l'aggiornamento persistendo nuovamente l'intero elemento.
# shelve_withoutwriteback.py
import shelve
with shelve.open('test_shelf.db') as s:
print(s['key1'])
s['key1']['nuovo_valore'] = 'questo non esisteva prima'
with shelve.open('test_shelf.db', writeback=True) as s:
print(s['key1'])
In questo esempio il dizionario a key1
non viene nuovamente conservato; quando lo shelf verrà nuovamente aperto, le modifiche non saranno conservate.
$ python3 shelve_create.py $ python3 shelve_withoutwriteback.py {'int': 10, 'float': 9.5, 'string': 'Dati di esempio'} {'int': 10, 'float': 9.5, 'string': 'Dati di esempio'}
Per catturare automaticamente modifiche a oggetti volatili conservati nello shelf, si apra il database abilitando la riscrittura. Il flag writeback
fa sì che tutti gli oggetti recuperati dal database vengano memorizzati usando una cache in memoria. Ciascun oggetto in cache viene riscritto nel database quando lo shelf viene chiuso.
# shelve_writeback.py
import shelve
import pprint
with shelve.open('test_shelf.db', writeback=True) as s:
print('Dati iniziali:')
pprint.pprint(s['key1'])
s['key1']['nuovo_valore'] = 'questo non esisteva prima'
print('\nModificato:')
pprint.pprint(s['key1'])
with shelve.open('test_shelf.db', writeback=True) as s:
print('\nPreservato:')
pprint.pprint(s['key1'])
Sebbene vengano ridotte le possibilità di errore da parte del programmatore, e venga resa la persistenza dell'oggetto più trasparente, l'utilizzo della modalità di riscrittura potrebbe non essere quanto desiderato in ogni occasione. La cache consuma memoria supplememtare mentre lo shelf è aperto, e le interruzioni causate dalla riscrittura nel database di ogni oggetto conservato nella cache rallentano l'applicazione. Vengono riscritti nel database tutti gli oggetti in cache in quanto non vi è modo di sapere quale di essi è stato modificato. Se l'applicazione legge più dati di quanti ne scrive, la riscrittura avrà un impatto non nencessario sulle prestazioni.
$ python3 shelve_create.py $ python3 shelve_writeback.py Dati iniziali: {'float': 9.5, 'int': 10, 'string': 'Dati di esempio'} Modificato: {'float': 9.5, 'int': 10, 'nuovo_valore': 'questo non esisteva prima', 'string': 'Dati di esempio'} Preservato: {'float': 9.5, 'int': 10, 'nuovo_valore': 'questo non esisteva prima', 'string': 'Dati di esempio'}
Tipi di Shelf Specifici
Gli esempi precedenti usano tutti l'implementazione predefinita. Usando shelve.open()
in luogo della diretta implementazione è un modello di uso comune, specialmente se non importa quale tipo di database sia usato per la conservazione dei dati. A volte, tuttavia, quando il formato del database è importante, si utilizzi DbfilenameShelf
oppure BsdDbShelf
direttamente, e financo si subclassi Shelf
per una soluzione personalizzata.
Vedere anche:
- shelve
- La documentazione della libreria standard per questo modulo.
- dbm
- Il modulo dbm trova una libreria DBM disponibile per creare un nuovo database.
- feedcache
- Il modulo feedcache usa shelve come opzione di conservazione predefinita.
- shove
- shove implementa una API simile ma con più formati di back-end