Python pickle vs json

  1. Einführung in json
    json (JavaScript Object Notation) ist ein leichtes Datenaustauschformat, das einfach zu lesen und zu schreiben ist. Das JSON-Modul in Python bietet eine Reihe von Funktionen zum Kodieren und Dekodieren von JSON-Daten. Es unterstützt die Konvertierung zwischen den grundlegenden Datentypen von Python (wie Wörterbüchern, Listen, Zeichenfolgen, Ganzzahlen usw.) und JSON-Datenformaten.
  2. Einführung in Pickle
    Pickle ist das Serialisierungsmodul von Python, das Python-Objekte im Binärformat in Dateien speichern oder über das Netzwerk übertragen kann. Der Vorteil von pickle besteht darin, dass es fast jedes Python-Objekt, einschließlich benutzerdefinierter Objekte, serialisieren kann, ohne dass eine spezielle Verarbeitung des Objekts erforderlich ist. Das Pickle-Modul bietet eine Reihe von Funktionen zum Serialisieren und Deserialisieren von Python-Objekten.

JSON eignet sich für den Datenaustausch zwischen verschiedenen Systemen und Sprachen sowie für menschenlesbare Konfigurationsdateien. Pickle eignet sich am besten, wenn Sie komplexe Python-Objekte beibehalten müssen oder wenn Sie in einer reinen Python-Umgebung arbeiten.

>>> import json oder import pickle

Die Funktion dump bekommt eine Python-Instanz übergeben, die aus den in der vorangegangenen Tabelle aufgeführten Datentypen bestehen darf, und speichert diese in ein zum Schreiben geöffnetes Dateiobjekt.

with open("eintrag.json", "w") as f:
json.dump(eintrag, f)

oder

with open('eintrag.pkl', 'wb') as f:
pickle.dump(eintrag, f)

Beachten Sie, dass JSON ein menschenlesbares Datenformat ist. Das Dateiobjekt muss daher nicht wie bei pickle im Binärmodus geöffnet werden. Analog zu dump gibt die Funktion dumps die JSON-Repräsentation einer Instanz als String zurück.

>>> s = json.dumps(eintrag)
>>> s
'{"Vorname": "Mandy", "Nachname": "Seider", "Adresse": ["Erpelweg", 12, 12345, "Entenhausen"], "Alter": 47}'

Die gespeicherten Daten können nun mit den korrespondierenden Funktionen load und loads wieder eingelesen und in eine Python-Instanz zurückkonvertiert werden:

>>> with open("eintrag.json", "r") as f:
... print(json.load(f))
{'Vorname': 'Donald', 'Nachname': 'Duck', 'Adresse': ['Erpelweg', 12, 12345, 'Entenhausen'], 'Alter': 81}
>>> json.loads(s)
{'Vorname': 'Donald', 'Nachname': 'Duck', 'Adresse': ['Erpelweg', 12, 12345, 'Entenhausen'], 'Alter': 81}

Beispielcode mit json:

from tkinter import *
import tkinter as tk
import json
import re
import tkinter.messagebox

# Dictionary initialisieren
try:
    with open('russisch-dict.json', 'r', encoding='utf-8') as f:
        russisch_dict = json.load(f)
except FileNotFoundError:
    russisch_dict = {
        "сбн.": "fM",
        "уб": "Abn",
        "пр.": "Zun"
    }
    with open('russisch-dict.json', 'w', encoding='utf-8') as f:
        json.dump(russisch_dict, f, ensure_ascii=False, indent=4)
except Exception as e:
    tkinter.messagebox.showerror(title="Fehler", message=f"Fehler beim Initialisieren: {str(e)}")

def hinzufuegen():
    # Werte aus den Eingabefeldern holen
    russisch = eingabefeld_russisch.get("1.0", END).strip()
    deutsch = eingabefeld_deutsch.get("1.0", END).strip()

    # Überprüfen, ob beide Felder ausgefüllt sind
    if russisch and deutsch:
        russisch_dict[russisch] = deutsch  # Eintrag ins Dictionary hinzufügen
        print(f"Eintrag hinzugefügt: {russisch} -> {deutsch}")
        tkinter.messagebox.showinfo(title="Eintrag ok", message="Eintrag erfolgreich hinzugefügt")
        print("Aktuelles Dictionary:", russisch_dict)
        # Felder leeren
        eingabefeld_russisch.delete("1.0", END)
        eingabefeld_deutsch.delete("1.0", END)
        
        # Dictionary nach jedem Hinzufügen speichern
        with open('russisch-dict.json', 'w', encoding='utf-8') as f:
            json.dump(russisch_dict, f, ensure_ascii=False, indent=4)
    else:
        print("Bitte beide Felder ausfüllen!")

def uebersetzen():
    # Eingabetext aus dem Eingabefeld holen
    eingabe_text = eingabefeld.get("1.0", END).strip()
    
    # Text in Zeilen aufteilen
    zeilen = eingabe_text.split('\n')
    
    uebersetzt = []

    for zeile in zeilen:
        # Teile jede Zeile in Elemente
        elemente = re.findall(r'\d+pb-?|\d+aum|an\.mág\.de|\w+\.?|\([^)]*\)|:', zeile)
        
        uebersetzt_zeile = []
        for element in elemente:
            if element.isdigit() or element == ':' or element.startswith('('):
                uebersetzt_zeile.append(element)
            else:
                # Übersetze zusammengesetzte Elemente
                uebersetztes_element = element
                for key, value in russisch_dict.items():
                    uebersetztes_element = uebersetztes_element.replace(key, value)
                uebersetzt_zeile.append(uebersetztes_element)
        
        uebersetzt.append(' '.join(uebersetzt_zeile))
    
    ergebnis = '\n'.join(uebersetzt)
    ausgabefeld.delete("1.0", END)
    ausgabefeld.insert(END, ergebnis)

def felder_loeschen():
    eingabefeld.delete("1.0", END)
    ausgabefeld.delete("1.0", END)

def kopieren():
    root.clipboard_clear()
    root.clipboard_append(ausgabefeld.get("1.0", END))

def show_dictionary():
    try:
        with open('russisch-dict.json', 'r', encoding='utf-8') as f:
            loaded_dict = json.load(f)
        
        popup = tk.Toplevel()
        popup.title("Dictionary Inhalt")
        
        text_widget = tk.Text(popup, wrap=tk.WORD, width=40, height=20)
        text_widget.pack(padx=10, pady=10)
        
        for key, value in loaded_dict.items():
            text_widget.insert(tk.END, f"{key}: {value}\n")
        
        text_widget.config(state=tk.DISABLED)
        
    except FileNotFoundError:
        messagebox.showerror("Fehler", "Die Dictionary-Datei wurde nicht gefunden.")
    except Exception as e:
        messagebox.showerror("Fehler", f"Fehler beim Laden des Dictionaries: {str(e)}")

# GUI erstellen
root = Tk()
root.title("Häkelanleitung Übersetzer")
root.geometry("500x1000")

eingabefeld = Text(root, height=20, width=50)
eingabefeld.pack(pady=10)

top_frame = Frame(root)
top_frame.pack(pady=5)

# Buttons in der oberen Reihe
bestaetigung = Button(top_frame, text="Auf deutsch übersetzen", command=uebersetzen)
bestaetigung.pack(side=LEFT, padx=5)

kopieren_button = Button(top_frame, text="Übersetzung kopieren", command=kopieren)
kopieren_button.pack(side=LEFT, padx=5)

loeschen_button = Button(top_frame, text="Eingaben löschen", command=felder_loeschen)
loeschen_button.pack(side=LEFT, padx=5)

# Abbrechen-Button in einer separaten Reihe
abbrechen_button = Button(root, text="Abbrechen", command=root.destroy)
abbrechen_button.pack(pady=5)

# Ausgabefeld
ausgabefeld = Text(root, height=20, width=50)
ausgabefeld.pack(pady=10)

Label(root, text="russischer Begriff:").pack(pady=5)
eingabefeld_russisch = Text(root, height=2, width=30)
eingabefeld_russisch.pack(pady=10)

Label(root, text="Deutsche Übersetzung:").pack(pady=5)
eingabefeld_deutsch = Text(root, height=2, width=30)
eingabefeld_deutsch.pack(pady=10)

Button(root, text="Hinzufügen", command=hinzufuegen).pack(pady=10)

# Button zum Anzeigen des Dictionaries
show_dict_button = Button(root, text="Dictionary anzeigen", command=show_dictionary)
show_dict_button.pack(pady=5)

root.mainloop()

Beispiel mit pickle:

from tkinter import *
import tkinter as tk
import pickle
import re
import tkinter.messagebox

# Dictionary initialisieren
try:
russisch_dict = {
"сбн.": "fM",
"уб": "Abn",
"пр.": "Zun"
}
except Exception as e:
tkinter.messagebox.showerror(title="Fehler", message=f"Fehler beim Initialisieren: {str(e)}")

# Speichern des Dictionaries
with open('russisch-dict.pkl', 'wb') as f:
pickle.dump(russisch_dict, f)


def hinzufuegen():
# Werte aus den Eingabefeldern holen
russisch = eingabefeld_russisch.get("1.0", END).strip()
deutsch = eingabefeld_deutsch.get("1.0", END).strip()

# Überprüfen, ob beide Felder ausgefüllt sind
if russisch and deutsch:
russisch_dict[russisch] = deutsch # Eintrag ins Dictionary hinzufügen
print(f"Eintrag hinzugefügt: {russisch} -> {deutsch}")
tkinter.messagebox.showinfo(title="Eintrag ok", message="Eintrag erfolgreich hinzugefügt")
print("Aktuelles Dictionary:", russisch_dict)
# Felder leeren
eingabefeld_russisch.delete("1.0", END)
eingabefeld_deutsch.delete("1.0", END)

# Dictionary nach jedem Hinzufügen speichern
with open('russisch-dict.pkl', 'wb') as f:
pickle.dump(russisch_dict, f)

else:
print("Bitte beide Felder ausfüllen!")

def uebersetzen():
# Eingabetext aus dem Eingabefeld holen
eingabe_text = eingabefeld.get("1.0", END).strip()

# Text in Zeilen aufteilen
zeilen = eingabe_text.split('\n')

uebersetzt = []

for zeile in zeilen:
# Teile jede Zeile in Elemente
elemente = re.findall(r'\d+pb-?|\d+aum|an\.mág\.de|\w+\.?|\([^)]*\)|:', zeile)

uebersetzt_zeile = []
for element in elemente:
if element.isdigit() or element == ':' or element.startswith('('):
uebersetzt_zeile.append(element)
else:
# Übersetze zusammengesetzte Elemente
uebersetztes_element = element
for key, value in russisch_dict.items():
uebersetztes_element = uebersetztes_element.replace(key, value)
uebersetzt_zeile.append(uebersetztes_element)

uebersetzt.append(' '.join(uebersetzt_zeile))

ergebnis = '\n'.join(uebersetzt)
ausgabefeld.delete("1.0", END)
ausgabefeld.insert(END, ergebnis)

def felder_loeschen():
eingabefeld.delete("1.0", END)
ausgabefeld.delete("1.0", END)

def kopieren():
root.clipboard_clear()
root.clipboard_append(ausgabefeld.get("1.0", END))
def show_dictionary():
try:
with open('russisch-dict.pkl', 'rb') as f:
loaded_dict = pickle.load(f)


popup = tk.Toplevel()
popup.title("Dictionary Inhalt")

text_widget = tk.Text(popup, wrap=tk.WORD, width=40, height=20)
text_widget.pack(padx=10, pady=10)

for key, value in loaded_dict.items():
text_widget.insert(tk.END, f"{key}: {value}\n")

text_widget.config(state=tk.DISABLED)

except FileNotFoundError:
messagebox.showerror("Fehler", "Die Dictionary-Datei wurde nicht gefunden.")
except Exception as e:
messagebox.showerror("Fehler", f"Fehler beim Laden des Dictionaries: {str(e)}")


# GUI erstellen
root = Tk()
root.title("Häkelanleitung Übersetzer")
root.geometry("500x1000")

eingabefeld = Text(root, height=20, width=50)
eingabefeld.pack(pady=10)

top_frame = Frame(root)
top_frame.pack(pady=5)

# Buttons in der oberen Reihe
bestaetigung = Button(top_frame, text="Auf deutsch übersetzen", command=uebersetzen)
bestaetigung.pack(side=LEFT, padx=5)

kopieren_button = Button(top_frame, text="Übersetzung kopieren", command=kopieren)
kopieren_button.pack(side=LEFT, padx=5)

loeschen_button = Button(top_frame, text="Eingaben löschen", command=felder_loeschen)
loeschen_button.pack(side=LEFT, padx=5)

# Abbrechen-Button in einer separaten Reihe
abbrechen_button = Button(root, text="Abbrechen", command=root.destroy)
abbrechen_button.pack(pady=5)

# Ausgabefeld
ausgabefeld = Text(root, height=20, width=50)
ausgabefeld.pack(pady=10)

Label(root, text="russischer Begriff:").pack(pady=5)
eingabefeld_russisch = Text(root, height=2, width=30)
eingabefeld_russisch.pack(pady=10)

Label(root, text="Deutsche Übersetzung:").pack(pady=5)
eingabefeld_deutsch = Text(root, height=2, width=30)
eingabefeld_deutsch.pack(pady=10)

Button(root, text="Hinzufügen", command=hinzufuegen).pack(pady=10)

# Button zum Anzeigen des Dictionaries
show_dict_button = Button(root, text="Dictionary anzeigen", command=show_dictionary)
show_dict_button.pack(pady=5)

root.mainloop()


Umstellung von pickle auf json:

Die Hauptänderungen sind:

  1. import json statt import pickle
  2. Die Datei wird nun als ‚russisch-dict.json‘ gespeichert und geladen.
  3. json.dump() und json.load() werden anstelle von pickle.dump() und pickle.load() verwendet.
  4. Bei json.dump() werden zusätzliche Parameter verwendet: ensure_ascii=False um nicht-ASCII-Zeichen korrekt zu speichern, und indent=4 für eine leserliche Formatierung der JSON-Datei.
  5. Beim Öffnen der JSON-Datei wird encoding='utf-8' verwendet, um Unicode-Zeichen korrekt zu handhaben.

Diese Änderungen machen das Speichern und Laden des Wörterbuchs kompatibel mit JSON, was im Vergleich zu pickle sicherer und lesbarer ist.