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_PROTOCOL erstellte 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 True gesetzt ist, werden alle zugegriffenen Einträge im Speicher zwischengespeichert und beim Aufruf von sync() und close() 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_PROTOCOL wird 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 Sie shelve.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 True geö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 mit close() automatisch aufgerufen.

Shelf.close()

Synchronisiert und schließt das persistente dict-Objekt. Operationen auf einem geschlossenen Shelf schlagen mit einem ValueError fehl.

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.ndbm oder dbm.gnu) hängt davon ab, welche Schnittstelle verfügbar ist. Daher ist es nicht sicher, die Datenbank direkt mit dbm zu öffnen. Die Datenbank unterliegt auch (leider) den Einschränkungen von dbm, 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 shelve unterstü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.ndbm die 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_PROTOCOL erstellte Pickles zur Serialisierung von Werten verwendet. Die Version des Pickle-Protokolls kann mit dem Parameter protocol angegeben werden. Siehe die Dokumentation zu pickle für eine Diskussion der Pickle-Protokolle.

Wenn der Parameter writeback True ist, 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 der with-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_PROTOCOL wird nun als Standard-Pickle-Protokoll verwendet.

class shelve.BsdDbShelf(dict, protocol=None, writeback=False, keyencoding='utf-8')

Eine Unterklasse von Shelf, die die Methoden first(), next(), previous(), last() und set_location() bereitstellt. Diese sind im Drittanbieter-Modul bsddb von 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 Funktionen bsddb.hashopen(), bsddb.btopen() oder bsddb.rnopen() erreicht. Die optionalen Parameter protocol, writeback und keyencoding haben die gleiche Bedeutung wie bei der Klasse Shelf.

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 mit dbm.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 Funktion open(). Die optionalen Parameter protocol und writeback haben die gleiche Bedeutung wie für die Klasse Shelf.

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

Siehe auch

Modul dbm

Generische Schnittstelle zu dbm-ähnlichen Datenbanken.

Modul pickle

Objektserialisierung, die von shelve verwendet wird.