shelve — Python object persistence¶
Quellcode: Lib/shelve.py
Ein „Shelf“ ist ein persistentes, Wörterbuch-ähnliches Objekt. Der Unterschied zu „dbm“-Datenbanken besteht darin, dass die Werte (nicht die Schlüssel!) in einem Shelf im Wesentlichen beliebige Python-Objekte sein können – alles, was das pickle-Modul verarbeiten kann. Dies schließt die meisten Klasseninstanzen, rekursive Datentypen und Objekte mit vielen gemeinsamen Unterobjekten ein. Die Schlüssel sind normale Zeichenketten.
- shelve.open(filename, flag='c', protocol=None, writeback=False)¶
Öffnet ein persistentes Wörterbuch. Der angegebene Dateiname ist der Basisdateiname für die zugrunde liegende Datenbank. Als Nebeneffekt kann dem Dateinamen eine Erweiterung hinzugefügt und mehr als eine Datei erstellt werden. Standardmäßig wird die zugrunde liegende Datenbankdatei zum Lesen und Schreiben geöffnet. Der optionale Parameter flag hat die gleiche Bedeutung wie der Parameter flag von
dbm.open().Standardmäßig werden mit
pickle.DEFAULT_PROTOCOLerstellte Pickles zur Serialisierung von Werten verwendet. Die Version des Pickle-Protokolls kann mit dem Parameter protocol angegeben werden.Aufgrund der Python-Semantik kann ein Shelf nicht wissen, wann ein veränderlicher persistenter Dictionary-Eintrag geändert wird. Standardmäßig werden geänderte Objekte *nur* beim Zuweisen zum Shelf geschrieben (siehe Beispiel). Wenn der optionale Parameter writeback auf
Truegesetzt ist, werden alle zugegriffenen Einträge im Speicher zwischengespeichert und beim Aufruf vonsync()undclose()zurückgeschrieben. Dies kann es praktischer machen, veränderliche Einträge im persistenten Wörterbuch zu ändern, aber wenn auf viele Einträge zugegriffen wird, kann dies zu einem enormen Speicherverbrauch für den Cache führen und den Schließvorgang sehr langsam machen, da alle zugegriffenen Einträge zurückgeschrieben werden (es gibt keine Möglichkeit festzustellen, auf welche veränderlichen Einträge zugegriffen wurde oder welche tatsächlich geändert wurden).Geändert in Version 3.10:
pickle.DEFAULT_PROTOCOLwird nun als Standard-Pickle-Protokoll verwendet.Geändert in Version 3.11: Akzeptiert pfadähnliche Objekte für den Dateinamen.
Hinweis
Verlassen Sie sich nicht auf das automatische Schließen des Shelfs; rufen Sie immer explizit
close()auf, wenn Sie es nicht mehr benötigen, oder verwenden Sieshelve.open()als Kontextmanager.with shelve.open('spam') as db: db['eggs'] = 'eggs'
Warnung
Da das Modul shelve auf pickle basiert, ist es unsicher, ein Shelf aus einer nicht vertrauenswürdigen Quelle zu laden. Wie bei pickle kann das Laden eines Shelfs beliebigen Code ausführen.
Shelf-Objekte unterstützen die meisten Methoden und Operationen von Wörterbüchern (außer Kopieren, Konstruktoren und Operatoren | und |=). Dies erleichtert die Umstellung von wörterbuchbasierten Skripten auf solche, die persistente Speicherung erfordern.
Zwei zusätzliche Methoden werden unterstützt
- Shelf.sync()¶
Schreibt alle Einträge im Cache zurück, wenn das Shelf mit writeback auf
Truegeöffnet wurde. Außerdem wird der Cache geleert und die persistente Datenbank auf der Festplatte synchronisiert, sofern möglich. Dies wird beim Schließen des Shelfs mitclose()automatisch aufgerufen.
- Shelf.close()¶
Synchronisiert und schließt das persistente dict-Objekt. Operationen auf einem geschlossenen Shelf schlagen mit einem
ValueErrorfehl.
Siehe auch
Rezept für persistentes Wörterbuch mit weit verbreiteten Speicherformaten und der Geschwindigkeit nativer Wörterbücher.
Beschränkungen¶
Die Wahl des zu verwendenden Datenbankpakets (z. B.
dbm.ndbmoderdbm.gnu) hängt davon ab, welche Schnittstelle verfügbar ist. Daher ist es nicht sicher, die Datenbank direkt mitdbmzu öffnen. Die Datenbank unterliegt auch (leider) den Einschränkungen vondbm, falls dieses verwendet wird – dies bedeutet, dass (die gepickelte Darstellung) der in der Datenbank gespeicherten Objekte ziemlich klein sein sollte, und in seltenen Fällen können Schlüsselkollisionen dazu führen, dass die Datenbank Aktualisierungen ablehnt.Das Modul
shelveunterstützt keinen *gleichzeitigen* Lese-/Schreibzugriff auf gespeicherte Objekte. (Mehrere gleichzeitige Lesezugriffe sind sicher.) Wenn ein Programm ein Shelf zum Schreiben geöffnet hat, sollte kein anderes Programm es zum Lesen oder Schreiben geöffnet haben. Unix-Datei-Sperren können verwendet werden, um dies zu lösen, aber dies variiert je nach Unix-Version und erfordert Kenntnisse über die verwendete Datenbankimplementierung.Unter macOS kann
dbm.ndbmdie Datenbankdatei bei Aktualisierungen stillschweigend beschädigen, was zu harten Abstürzen beim Versuch, aus der Datenbank zu lesen, führen kann.
- class shelve.Shelf(dict, protocol=None, writeback=False, keyencoding='utf-8')¶
Eine Unterklasse von
collections.abc.MutableMapping, die gepickelte Werte im dict-Objekt speichert.Standardmäßig werden mit
pickle.DEFAULT_PROTOCOLerstellte Pickles zur Serialisierung von Werten verwendet. Die Version des Pickle-Protokolls kann mit dem Parameter protocol angegeben werden. Siehe die Dokumentation zupicklefür eine Diskussion der Pickle-Protokolle.Wenn der Parameter writeback
Trueist, hält das Objekt einen Cache aller zugegriffenen Einträge und schreibt sie beim Synchronisieren und Schließen in das dict zurück. Dies ermöglicht natürliche Operationen auf veränderlichen Einträgen, kann aber deutlich mehr Speicher verbrauchen und das Synchronisieren und Schließen lange dauern lassen.Der Parameter keyencoding ist die Kodierung, die verwendet wird, um Schlüssel zu kodieren, bevor sie mit dem zugrunde liegenden dict verwendet werden.
Ein
Shelf-Objekt kann auch als Kontextmanager verwendet werden, in diesem Fall wird es automatisch geschlossen, wenn derwith-Block endet.Geändert in Version 3.2: Der Parameter keyencoding wurde hinzugefügt; zuvor wurden Schlüssel immer in UTF-8 kodiert.
Geändert in Version 3.4: Unterstützung für Kontextmanager hinzugefügt.
Geändert in Version 3.10:
pickle.DEFAULT_PROTOCOLwird nun als Standard-Pickle-Protokoll verwendet.
- class shelve.BsdDbShelf(dict, protocol=None, writeback=False, keyencoding='utf-8')¶
Eine Unterklasse von
Shelf, die die Methodenfirst(),next(),previous(),last()undset_location()bereitstellt. Diese sind im Drittanbieter-Modulbsddbvon pybsddb verfügbar, aber nicht in anderen Datenbankmodulen. Das an den Konstruktor übergebene dict-Objekt muss diese Methoden unterstützen. Dies wird im Allgemeinen durch Aufruf einer der Funktionenbsddb.hashopen(),bsddb.btopen()oderbsddb.rnopen()erreicht. Die optionalen Parameter protocol, writeback und keyencoding haben die gleiche Bedeutung wie bei der KlasseShelf.
- class shelve.DbfilenameShelf(filename, flag='c', protocol=None, writeback=False)¶
Eine Unterklasse von
Shelf, die einen filename anstelle eines Wörterbuch-ähnlichen Objekts akzeptiert. Die zugrunde liegende Datei wird mitdbm.open()geöffnet. Standardmäßig wird die Datei erstellt und für Lesen und Schreiben geöffnet. Der optionale Parameter flag hat die gleiche Bedeutung wie für die Funktionopen(). Die optionalen Parameter protocol und writeback haben die gleiche Bedeutung wie für die KlasseShelf.
Beispiel¶
Zusammenfassend die Schnittstelle (key ist eine Zeichenkette, data ist ein beliebiges Objekt)
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