In Python werden zur Serialisierung (Umwandlung von Objekten in eine Bytefolge oder einen String zur Speicherung/Übertragung) die Module pickle und json verwendet:
Die Verwendung von Pickle zur Speicherung/Übertragung von Daten zwischen unkontrollierten Parteien ist riskant, da bei der Deserialisierung beliebiger schädlicher Code ausgeführt werden kann. json hat dieses Manko nicht.
Beispiel für die Verwendung:
import pickle import json # Pickle (binäre Serialisierung) data = {'x': 10, 'func': lambda x: x + 1} with open('data.pkl', 'wb') as f: pickle.dump(data, f) # JSON (nur einfache Objekte) data = {'x': 10, 'y': [1, 2, 3]} with open('data.json', 'w') as f: json.dump(data, f)
Frage: Kann man pickle zur Serialisierung und Speicherung beliebiger Python-Objekte zwischen Sitzungen verwenden? Warum wird dieses Verfahren nicht empfohlen, um Benutzerdaten zu speichern?
Antwort:
Nein, pickle überall zu verwenden ist eine schlechte Praxis. Neben der Sicherheit (bei der Lade eines "fremden" pickled-Objekts kann die Ausführung kompromittiert werden) gibt es das Problem der Kompatibilität zwischen verschiedenen Python-Versionen oder Klassen - serialisierte Objekte können möglicherweise nicht geladen werden oder sich fehlerhaft verhalten, wenn sich die Struktur der Klassen geändert hat.
Beispiel:
# Laden einer pickle-Datei, die Struktur der Klasse hat sich geändert import pickle with open('old_version.pkl', 'rb') as f: obj = pickle.load(f) # AttributeError oder Strukturunterschiede
Geschichte
In einem großen Projekt wurde pickle zur Speicherung von Benutzerprofilen verwendet. Nach einem Update der Python-Version und einer Änderung der Klassen verlor die Struktur der serialisierten Objekte die Kompatibilität, was zu einem Systemausfall und dem Verlust der meisten Benutzerdaten führte.
In einem Webservice wurde pickle für die Benutzersitzungen verwendet. Ein böswilliger Akteur lud ein schädliches pickled-Objekt hoch, was es ermöglichte, Code-Injection auf dem Server durchzuführen.
Der Versuch, Funktionen über pickle zu serialisieren, um sie über das Netzwerk zu übertragen, scheiterte in mehreren Umgebungen: pickled-Lambdas können nicht zwischen Maschinen mit unterschiedlichen Konfigurationen/versionen von Python übertragen werden.