19.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 String erzeugt, der 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 sehr gut geeignet. Folgende Datentypen können mithilfe von pickle serialisiert bzw. deserialisiert werden:
- None, True, False
- Numerische Datentypen (int, long, float, complex)
- str, unicode
- 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 muss beachtet werden, 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 von 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 drei verschiedene Formate, in denen pickle seine Daten speichern kann. Jedes dieser Formate hat eine Zahl, um es zu identifizieren:
Nummer | Beschreibung |
0 |
Der resultierende String besteht nur aus ASCII-Zeichen und kann deshalb auch von Menschen beispielsweise zu Debug-Zwecken gelesen werden. Das Protokoll 0 ist der Standard für das pickle-Modul und auch zu früheren Versionen von Python (< 2.3) kompatibel. |
1 |
Dieses Protokoll erzeugt einen Binärstring, der die Daten im Vergleich zur ASCII-Variante platzsparender speichert. Auch das Protokoll 1 ist abwärtskompatibel zu Python-Versionen vor 2.3. |
2 |
Neues Binärformat, das besonders für Klasseninstanzen optimiert wurde. Objekte, die mit dem Protokoll 2 serialisiert wurden, können nur von Python-Versionen ab 2.3 gelesen werden. |
Das Modul pickle bietet seine Funktionalität über zwei Schnittstellen an: eine imperative ü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
Die imperative Schnittstelle
pickle.dump(obj, file[, protocol])
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 kann das Protokoll für die Speicherung übergeben werden. Der Standardwert für protocol ist 0. Wird ein Binärformat angegeben, so muss das für file übergebene Dateiobjekt im binären Schreibmodus geöffnet worden sein.
>>> f = open("pickle-test.txt", "w") >>> pickle.dump([1, 2, 3], f)
Für file kann neben echten Dateiobjekten jedes Objekt übergeben werden, das eine write-Methode mit einem String-Parameter implementiert, zum Beispiel StringIO-Instanzen.
pickle.load(file)
Lädt das nächste serialisierte Objekt aus dem geöffneten Dateiobjekt, das für file übergeben wurde. Dabei erkennt load selbstständig, in welchem Fomat die Daten gespeichert wurden.
Das folgende Beispiel setzt voraus, dass im aktuellen Arbeitsverzeichnis eine Datei mit dem Namen pickle-test.txt existiert, die eine serialisierte Liste enthält:
>>> f = open("pickle-test.txt") >>> pickle.load(f) [1, 2, 3]
pickle.dumps(obj[, protocol])
Gibt die serialisierte Repräsentation von obj als String zurück, wobei der Parameter protocol angibt, welches der drei Serialisierungsproktokolle verwendet werden soll. Standardmäßig wird das ASCII-Protokoll mit der Kennung 0 verwendet.
>>> pickle.dumps([1, 2, 3]) '(lp0\nI1\naI2\naI3\na.'
pickle.loads(string)
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]
Die objektorientierte Scbnittstelle
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 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.
>>> p = pickle.Pickler(file("eine_datei.txt", "w"), 2) >>> p.dump({"vorname" : "Peter", "nachname" : "Kaiser"}) >>> 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.txt im aktuellen Arbeitsverzeichnis liegt:
>>> u = pickle.Unpickler(file("eine_datei.txt")) >>> u.load() {'nachname': 'Kaiser', 'vorname': 'Peter'} >>> u.load() [1, 2, 3, 4]
cPickle
Das Modul pickle ist komplett in Python implementiert und deshalb für sehr große Datenmengen langsam. Es existiert eine weitere Implementation des pickle-Moduls namens cPickle, die vollständig in der maschinennahen Sprache C geschrieben wurde.
Mit cPickle lassen sich Daten bis zu 1000-mal so schnell wie mit pickle serialisieren.
Als einzige Einschränkung muss dabei beachtet werden, dass die Bezeichner Pickler und Unpickler in cPickle keine wirklichen Klassen, sondern Funktionen sind. Deshalb können von ihnen keine eigenen Klassen abgeleitet werden.