2024-05-16 06:10:40
  • Hello!
  • Whats ya doin?
  • ByeBye

[&]

18.117.100.129

Porównanie modułów JSON i Pickle oraz Zadania

workshop: #py-ser-des.html

Python: Serializacja i deserializacja

Moduły pickle oraz json

Przygotowanie

  1. Uczeń posiada interpreter języka Python
  2. Utwórz katalog do pracy, np. 20-py-ser-des
1 Porównanie modułów serializacji danych

Wersje protokołów modułu pickle

  • wersja 0 protokołu

  • wersja 1 protokołu

  • wersja 2 protokołu

  • wersja 3 protokołu - dodana w Python 3.0 wspiera obiekty bajtowe; nie działa dla Python 2.x

  • wersja 4 protokołu - dodana w Python 3.4 (min. obsługa duzych obieków, więcej ich rodzajów oraz optymalizacje formatów). Domyślny od wersji Python 3.8

  • wersja 5 protokołu - dodana w Python 3.8

Tabela porównawcza

JSON Pickle
tekstowy format serializacji (unicode, utf-8) binarny format serializacji
czytelny dla człowieka nieczytelny dla człowieka
interoperabilny poza ekosystemem Python'a specyficzny dla języka Python
domyślnie reprezentuje podzbiór wbudowanych typów Pythona, bez obsługi klas pickle reprezentuje obszerny zbiór typów Python'a (wiele typów automatycznie, a złożone poprzez tzw. introspekcję)
deserializacja niezaufanych ciągów JSON nie stanowi zagrożenia deserializacja niezaufanych ciągów JSON jest ryzykiem uruchomienia niebezpiecznego kodu
2 Użycie modułów do serializacji

Aby móc serializować i deserializować dane wymagany jest import odpowiednich pakietów

  • import pickle dla formatu natywnego języka Python

  • import json dla formatu JSON (JavaScript Object Notation)

Podstawowe metody modułu Pickle

  • pickle.dumps( dane_Python ) - konwertuje dane natywne języka Python do formatu binarnego

  • pickle.Pickler( plik ).dump( dane_Python ) - j/w, lecz zapisuje dane do pliku

  • pickle.dump( dane_Python, plik ) - j/w

  • pickle.loads( dane_zserializowane ) odczytuje zserializowane dane do formatu obiektu języka Python

  • pickle.Unpickler( plik ).load() - j/w, lecz odczytuje dane z pliku

  • pickle.load( plik ) - j/w

Podstawowe metody modułu json

  • json.dumps( dane_Python ) - konwertuje dane natywne języka Python do formatu JSON

  • json.loads( dane_JSON ) - odczytuje zserializowane dane formatu JSON do formatu obiektu języka Python

  • json.JSONEncoder().encode( dane_JSON ) - j/w

Moduł Pickle

Typy danych jakie można zserializować

  • None, True oraz False

  • integer, float, complex number

  • string, byte, bytearray

  • krotki (tuple), listy, zbiory (set), słowniki (dict) z obiektami "pickle-able"

  • funkcje zdefiniowane na najwyższym poziomie modułu (def, bez lambda)

  • wbudowane funkcje modułu zdefiniowane na najwyższym poziomie modułu

  • klasy zdefiniowane na najwyższym poziomie modułu

  • instancje, których __dict__ lub rezultat wywołania __getstate__() jest "pickle-able"

3 Użycie modułów do serializacji i deserializacji

Przykład kodu App1.py obsługi modułu pickle

import io
import pickle
import copy

class Cos:
	attr = 'Atrybut klasy'

print("Klasa Cos z instancji cos:")
print(Cos)
print(Cos.attr)
print("")
# piklujemy klasę
pkcos = pickle.dumps(Cos)
# efekt
print(pkcos)
print("")
# odpiklowujemy
thing = pickle.loads( pkcos )
# efekt
print("Klasa Cos z instancji thing:")
print(thing)
print(thing.attr)
print("")
# zmiany wartości atrybutów
print("Atrybuty przed zmianą:")
cos = Cos
print("Cos  = "+cos.attr)
print("Thing= "+thing.attr)
cos.attr = "Jestem Coś"
thing.attr = "I am a Thing"
print("")
print("Atrybuty po zmianie:")
print("Cos  = "+cos.attr)
print("Thing= "+thing.attr)

Przykład kodu App2.py obsługi modułu json

import json
import copy

#jsonStr = "{ course:'ad', unit:'3pt4', lesson:'8', dateAt:'2022-03-29', topic:'Serializacja i deserializacja' }"
jsonStr = '{ "course":"ad", "unit":"3pt4", "lesson":"20", "dateAt":"2022-03-29", "topic":"Serializacja i deserializacja" }'
print("Ciąg string z danymi JSON")
print(jsonStr)
print("")
print("String z danymi JSON zdekodowany do...")
pyObj = json.loads(jsonStr)
print(pyObj)
print("")
print("Klucz=Wartość")
print("Kurs:	"+pyObj['course'])
print("Klasa:	"+pyObj['unit'])
print("Lekcja:	"+pyObj['lesson'])
print("Data:	"+pyObj['dateAt'])
print("Temat:	"+pyObj['topic'])
print("")
print("Zduplikowanie słownika (dict)")
lsn = copy.deepcopy(pyObj)	# duplikat, bez referencji
lsn['unit'] = '3pt5'
lsn['lesson'] = '34'
lsn['dateAt'] = '2022-04-04'
print(lsn)
print(pyObj)
print("")
print("Zakodowanie obiektu Python do stringa JSON")
jsonStr2 = json.dumps(lsn)
#jsonStr2 = json.JSONEncoder().encode(lsn)
print(jsonStr2)
#json.loads(json_file_1)

Przykład kodu App3.py obsługi instancji klasy

import io
import pickle

class Client:
	# podczas deserializacji metoda __init__ NIE jest wywoływana
	# natomiast właściwości atrybutów są przywracane
	def __init__(self, name):
		self.ip = "192.168.0.1"
		self.host = "teacherDesk"
		self.name = name
		print("Jestem initem "+self.host+" dla "+self.name)

	def save(obj):
		return (obj.__class__, obj.__dict__)

	def load(cls, attr):
		obj = cls.__new(cls)
		obj.__dict__.update(attr)
		return obj

c1 = Client("GP")
print(c1)
print("")
c2 = Client("RR")
print(c2)
print("")

# piklowanie instancji Client(GP)
c1p = pickle.dumps(c1)
print(c1p)
c1 = None	# wyczyszczenie instancji Client(GP)
print(c1)
# odpiklowujemy zapamiętaną instancję Client(GP)
c1 = pickle.loads(c1p)
print(c1.host+" "+c1.name)
print(c1)
print("")

#c3 = Client("BL")
#pkFile = 'tmp_pk'
#with open(pkFile, "wb") as fp:
##	c3p = pickle.Pickler(fp).dump(c3)
#	c3p = pickle.dump(c3, fp)

Przykład kodu Pack.py obsługi zapisu do pliku oraz NotClient.py do odczytu z pliku

Nie odnaleziono pliku!

Nie odnaleziono pliku!

Przykład kodu App4.py

Heelloo
Line no.2
Goodbye!
import io
import pickle

class TextReader:
    """Print and number lines in a text file."""

    def __init__(self, filename):
        self.filename = filename
        self.file = open(filename)
        self.lineno = 0

    def readline(self):
        self.lineno += 1
        line = self.file.readline()
        if not line:
            return None
        if line.endswith('\n'):
            line = line[:-1]
        return "%i: %s" % (self.lineno, line)

    def __getstate__(self):
        # Copy the object's state from self.__dict__ which contains
        # all our instance attributes. Always use the dict.copy()
        # method to avoid modifying the original state.
        state = self.__dict__.copy()
        # Remove the unpicklable entries.
        del state['file']
        return state

    def __setstate__(self, state):
        # Restore instance attributes (i.e., filename and lineno).
        self.__dict__.update(state)
        # Restore the previously opened file's state. To do so, we need to
        # reopen it and read from it until the line count is restored.
        file = open(self.filename)
        for _ in range(self.lineno):
            file.readline()
        # Finally, save the file.
        self.file = file

reader = TextReader("hello.txt")
print(reader.readline())
print(reader.readline())
new_reader = pickle.loads(pickle.dumps(reader))
print(new_reader.readline())

Podsumowanie

  1. Umiesz używać modułów pickle oraz json
  2. Potrafisz zapisać oraz odczytać plik z zserializowanymi danymi
  3. Zebraną wiedzę zastosujesz do projektu zaliczeniowego wraz z Web Sockets