33.4 Serialisierung von Instanzen – pickle 

Das Modul pickle (dt. »pökeln«) bietet komfortable Funktionen für das Serialisieren von Objekten. Beim Serialisieren eines Objekts wird ein bytes-Objekt erzeugt, das alle Informationen des Objekts speichert, sodass es später wieder durch das sogenannte Deserialisieren rekonstruiert werden kann.
Besonders für die dauerhafte Speicherung von Daten in Dateien ist pickle gut geeignet. Folgende Datentypen können mithilfe von pickle serialisiert bzw. deserialisiert werden:
- None, True, False
- numerische Datentypen (int, float, complex, bool)
- str, bytes
- sequenzielle Datentypen (tuple, list), Mengen (set, frozenset) und Dictionarys (dict), solange alle ihre Elemente auch von pickle serialisiert werden können
- globale Funktionen
- Built-in Functions
- globale Klassen
- Klasseninstanzen, deren Attribute serialisiert werden können
Bei Klassen und Funktionen müssen Sie beachten, dass solche Objekte beim Serialisieren nur mit ihrem Klassennamen gespeichert werden. Der Code einer Funktion oder die Definition der Klasse und ihre Attribute werden nicht gesichert. Wenn Sie also beispielsweise eine Instanz einer selbst definierten Klasse deserialisieren möchten, muss die Klasse in dem aktuellen Kontext genauso wie bei der Serialisierung definiert sein. Ist das nicht der Fall, wird ein UnpicklingError erzeugt.
Es gibt vier Formate, in denen pickle seine Daten speichern kann. Jedes dieser Formate hat eine Identifikationsnummer. Tabelle 33.9 listet die verfügbaren Protokolle auf und nennt die Version von Python, in der das jeweilige Protokoll eingeführt wurde:
Nummer | Eingeführt in | Bemerkungen |
---|---|---|
0 | – | ASCII-Format |
1 | – | Binärformat |
2 | Python 2.3 | Binärformat |
3 | Python 3.0 | Binärformat |
4 | Python 3.4 | Binärformat |
Tabelle 33.9 Die pickle-Protokolle
Das Modul pickle bietet seine Funktionalität über zwei Schnittstellen an: eine über die Funktionen dump und load und eine objektorientierte mit den Klassen Pickler und Unpickler.
Um pickle verwenden zu können, muss das Modul importiert werden:
>>> import pickle
33.4.1 Funktionale Schnittstelle 

pickle.dump(obj, file, [protocol])
Diese Funktion schreibt die Serialisierung von obj in das Dateiobjekt file. Das übergebene Dateiobjekt muss dabei für den Schreibzugriff geöffnet worden sein.
Mit dem Parameter protocol können Sie das Protokoll für die Speicherung übergeben. Der Standardwert für protocol ist 3. Geben Sie ein Binärformat an, muss das für file übergebene Dateiobjekt im binären Schreibmodus geöffnet worden sein.
>>> with open("pickle-test.dat", "wb") as f:
... pickle.dump([1, 2, 3], f)
Für file können Sie neben echten Dateiobjekten jedes Objekt übergeben, das eine write-Methode mit einem String-Parameter implementiert, zum Beispiel StringIO-Instanzen.
pickle.load(file)
Diese Funktion lädt – ausgehend von der aktuellen Leseposition des Dateiobjekts file – das nächste serialisierte Objekt. Dabei erkennt load selbstständig, in welchem Format die Daten gespeichert wurden.
Das folgende Beispiel setzt voraus, dass im aktuellen Arbeitsverzeichnis eine Datei mit dem Namen pickle-test.dat existiert, die eine serialisierte Liste enthält:
>>> with open("pickle-test.dat", "rb") as f:
... print(pickle.load(f))
[1, 2, 3]
Auch hier müssen Sie darauf achten, die Dateien im Binärmodus zu öffnen, wenn Sie andere pickle-Protokolle als 0 verwenden.
pickle.dumps(obj, [protocol])
Diese Funktion gibt die serialisierte Repräsentation von obj als bytes-String zurück, wobei der Parameter protocol angibt, welches der drei Serialisierungsprotokolle verwendet werden soll. Standardmäßig wird das Protokoll mit der Kennung 3 benutzt.
>>> pickle.dumps([1, 2, 3])
b'\x80\x03]q\x00(K\x01K\x02K\x03e.'
pickle.loads(string)
Diese Funktion stellt das in string serialisierte Objekt wieder her. Das verwendete Protokoll wird dabei automatisch erkannt, und überflüssige Zeichen am Ende des Strings werden ignoriert:
>>> s = pickle.dumps([1, 2, 3])
>>> pickle.loads(s)
[1, 2, 3]
33.4.2 Objektorientierte Schnittstelle 

Gerade dann, wenn viele Objekte in dieselbe Datei serialisiert werden sollen, ist es lästig und schlecht für die Lesbarkeit, jedes Mal das Dateiobjekt und das zu verwendende Protokoll bei den Aufrufen von dump mit anzugeben.
Neben den schon vorgestellten Modulfunktionen gibt es deshalb noch die beiden Klassen Pickler und Unpickler.
Pickler und Unpickler haben außerdem den Vorteil, dass Klassen von ihnen erben und so die Serialisierung anpassen können.
pickle.Pickler(file, [protocol])
Die beiden Parameter file und protocol haben die gleiche Bedeutung wie bei der pickle.dump-Funktion. Das resultierende Pickler-Objekt hat eine Methode namens dump, die als Parameter ein Objekt erwartet, das serialisiert werden soll.
Alle an die load-Methode gesendeten Objekte werden in das beim Erzeugen der Pickler-Instanz übergebene Dateiobjekt geschrieben.
>>> with open("eine_datei.dat", "wb") as f:
... p = pickle.Pickler(f, 2)
... p.dump({"vorname" : "Donald", "nachname" : "Duck"})
... p.dump([1, 2, 3, 4])
pickle.Unpickler(file)
Das Gegenstück zu Pickler ist Unpickler, um aus der übergebenen Datei die ursprünglichen Daten wiederherzustellen. Unpickler-Instanzen besitzen eine parameterlose Methode namens load, die jeweils das nächste Objekt aus der Datei liest.
Das folgende Beispiel setzt voraus, dass die im Beispiel zur Pickler-Klasse erzeugte Datei eine_datei.dat im aktuellen Arbeitsverzeichnis liegt:
>>> with open("eine_datei.dat", "rb") as f:
... u = pickle.Unpickler(f)
... print(u.load())
... print(u.load())
{'vorname': 'Donald', 'nachname': 'Duck'}
[1, 2, 3, 4]