Python zorientowany obiektowo - serializacja obiektów

W kontekście przechowywania danych serializacja to proces tłumaczenia struktur danych lub stanu obiektu na format, który może być przechowywany (na przykład w pliku lub buforze pamięci) lub przesyłany i rekonstruowany później.

Podczas serializacji obiekt jest przekształcany do formatu, który może być przechowywany, tak aby móc później deserializować go i ponownie utworzyć oryginalny obiekt z formatu serializowanego.

Marynata

Pickling to proces, w którym hierarchia obiektów Pythona jest konwertowana na strumień bajtów (zwykle nieczytelny dla człowieka), który ma zostać zapisany w pliku. Jest to również znane jako serializacja. Unpickling to operacja odwrotna, w której strumień bajtów jest konwertowany z powrotem do działającej hierarchii obiektów Pythona.

Pickle to najprostszy operacyjnie sposób przechowywania przedmiotu. Moduł Python Pickle to zorientowany obiektowo sposób przechowywania obiektów bezpośrednio w specjalnym formacie przechowywania.

Co to może zrobić?

  • Pickle może bardzo łatwo przechowywać i odtwarzać słowniki i listy.
  • Przechowuje atrybuty obiektów i przywraca je z powrotem do tego samego stanu.

Czego marynata nie może zrobić?

  • Nie zapisuje kodu obiektowego. Tylko wartości atrybutów.
  • Nie może przechowywać uchwytów plików ani gniazd połączeń.

Krótko mówiąc, można powiedzieć, że wytrawianie to sposób na przechowywanie i pobieranie zmiennych danych do i z plików, w których zmiennymi mogą być listy, klasy itp.

Aby coś marynować, musisz -

  • import marynaty
  • Napisz zmienną do pliku, na przykład
pickle.dump(mystring, outfile, protocol),

gdzie protokół trzeciego argumentu jest opcjonalny Aby coś usunąć, musisz -

Import marynaty

Napisz zmienną do pliku, na przykład

myString = pickle.load(inputfile)

Metody

Interfejs marynowania zapewnia cztery różne metody.

  • dump() - Metoda dump () serializuje do otwartego pliku (obiekt podobny do pliku).

  • dumps() - Serializuje do ciągu

  • load() - Deserializacja z otwartego obiektu.

  • loads() - Deserializacja z ciągu.

W oparciu o powyższą procedurę poniżej przykład „wytrawiania”.

Wynik

My Cat pussy is White and has 4 legs
Would you like to see her pickled? Here she is!
b'\x80\x03c__main__\nCat\nq\x00)\x81q\x01}q\x02(X\x0e\x00\x00\x00number_of_legsq\x03K\x04X\x05\x00\x00\x00colorq\x04X\x05\x00\x00\x00Whiteq\x05ub.'

Zatem w powyższym przykładzie utworzyliśmy instancję klasy Cat, a następnie wytrawiliśmy ją, przekształcając naszą instancję „Cat” w prostą tablicę bajtów.

W ten sposób możemy łatwo przechowywać tablicę bajtów w pliku binarnym lub w polu bazy danych i przywrócić ją z powrotem do pierwotnej postaci z naszej obsługi pamięci w późniejszym czasie.

Również jeśli chcesz stworzyć plik z piklowanym obiektem, możesz użyć metody dump () (zamiast dumps * () * one), przekazując również otwarty plik binarny, a wynik trawienia zostanie automatycznie zapisany w pliku.

[….]
binary_file = open(my_pickled_Pussy.bin', mode='wb')
my_pickled_Pussy = pickle.dump(Pussy, binary_file)
binary_file.close()

Wytrawianie

Proces, który pobiera tablicę binarną i konwertuje ją na hierarchię obiektów, nazywa się unpickling.

Proces rozpakowywania jest wykonywany za pomocą funkcji load () modułu pickle i zwraca pełną hierarchię obiektów z prostej tablicy bajtów.

Użyjmy funkcji load w naszym poprzednim przykładzie.

Wynik

MeOw is black
Pussy is white

JSON

JSON (JavaScript Object Notation) jest częścią standardowej biblioteki Pythona i jest lekkim formatem wymiany danych. Ludziom łatwo jest czytać i pisać. Łatwo jest analizować i generować.

Ze względu na swoją prostotę JSON to sposób, w jaki przechowujemy i wymieniamy dane, co jest realizowane za pomocą składni JSON i jest używany w wielu aplikacjach internetowych. Ponieważ jest w formacie czytelnym dla człowieka i może to być jeden z powodów wykorzystania go w transmisji danych, oprócz jego skuteczności podczas pracy z interfejsami API.

Przykład danych w formacie JSON jest następujący -

{"EmployID": 40203, "Name": "Zack", "Age":54, "isEmployed": True}

Python ułatwia pracę z plikami Json. Modułem używanym do tego celu jest moduł JSON. Ten moduł powinien być zawarty (wbudowany) w instalację Pythona.

Zobaczmy więc, jak możemy przekonwertować słownik Pythona na JSON i zapisać go do pliku tekstowego.

JSON na Python

Czytanie JSON oznacza konwersję JSON na wartość (obiekt) Pythona. Biblioteka json analizuje JSON do słownika lub listy w Pythonie. Aby to zrobić, używamy funkcji load () (ładowanie z łańcucha), jak poniżej -

Wynik

Poniżej znajduje się przykładowy plik json,

data1.json
{"menu": {
   "id": "file",
   "value": "File",
   "popup": {
      "menuitem": [
         {"value": "New", "onclick": "CreateNewDoc()"},
         {"value": "Open", "onclick": "OpenDoc()"},
         {"value": "Close", "onclick": "CloseDoc()"}
      ]
   }
}}

Powyższa treść (Data1.json) wygląda jak zwykły słownik. Możemy użyć pikle do przechowywania tego pliku, ale wynik nie jest czytelny dla człowieka.

JSON (Java Script Object Notification) to bardzo prosty format i to jeden z powodów jego popularności. Przyjrzyjmy się teraz wynikowi json za pomocą poniższego programu.

Wynik

Powyżej otwieramy plik json (data1.json) do odczytu, uzyskujemy procedurę obsługi pliku i przekazujemy do json.load i odzyskujemy obiekt. Kiedy próbujemy wydrukować dane wyjściowe obiektu, jest to to samo, co plik json. Chociaż typ obiektu to słownik, pojawia się jako obiekt Pythona. Pisanie do json jest proste, ponieważ widzieliśmy ten pikle. Powyżej ładujemy plik json, dodajemy kolejną parę klucz-wartość i zapisujemy ją z powrotem do tego samego pliku json. Teraz, jeśli zobaczymy plik data1.json, będzie on wyglądał inaczej, czyli nie w tym samym formacie, co poprzednio.

Aby nasze dane wyjściowe wyglądały tak samo (format czytelny dla człowieka), dodaj kilka argumentów do naszej ostatniej linii programu,

json.dump(conf, fh, indent = 4, separators = (‘,’, ‘: ‘))

Podobnie jak marynata, możemy wydrukować ciąg z zrzutami i załadować ładunkami. Poniżej znajduje się przykład tego,

YAML

YAML może być najbardziej przyjaznym dla człowieka standardem serializacji danych dla wszystkich języków programowania.

Moduł Python yaml nazywa się pyaml

YAML jest alternatywą dla JSON -

  • Human readable code - YAML jest formatem najbardziej czytelnym dla człowieka do tego stopnia, że ​​nawet jego treść na pierwszej stronie jest wyświetlana w YAML, aby to podkreślić.

  • Compact code - W YAML używamy wcięć białych znaków do oznaczenia struktury, a nie nawiasów.

  • Syntax for relational data - W przypadku odwołań wewnętrznych używamy kotwic (&) i aliasów (*).

  • One of the area where it is used widely is for viewing/editing of data structures - na przykład pliki konfiguracyjne, zrzucanie podczas debugowania i nagłówki dokumentów.

Instalowanie YAML

Ponieważ yaml nie jest modułem wbudowanym, musimy zainstalować go ręcznie. Najlepszym sposobem na zainstalowanie yamla na komputerze z systemem Windows jest użycie pip. Uruchom poniższe polecenie na terminalu Windows, aby zainstalować yaml,

pip install pyaml (Windows machine)
sudo pip install pyaml (*nix and Mac)

Po uruchomieniu powyższego polecenia ekran wyświetli coś takiego jak poniżej, w oparciu o aktualną najnowszą wersję.

Collecting pyaml
Using cached pyaml-17.12.1-py2.py3-none-any.whl
Collecting PyYAML (from pyaml)
Using cached PyYAML-3.12.tar.gz
Installing collected packages: PyYAML, pyaml
Running setup.py install for PyYAML ... done
Successfully installed PyYAML-3.12 pyaml-17.12.1

Aby to przetestować, przejdź do powłoki Pythona i zaimportuj moduł yaml, zaimportuj yaml, jeśli nie zostanie znaleziony żaden błąd, możemy powiedzieć, że instalacja się powiodła.

Po zainstalowaniu pyamla spójrzmy na poniższy kod,

script_yaml1.py

Powyżej stworzyliśmy trzy różne struktury danych, słownik, listę i krotkę. Na każdej strukturze wykonujemy yaml.dump. Ważnym punktem jest sposób wyświetlania danych wyjściowych na ekranie.

Wynik

Wyjście ze słownika wygląda na czyste .ie. kluczowa wartość.

Biała przestrzeń do oddzielania różnych obiektów.

Lista jest oznaczona myślnikiem (-)

Krotka jest oznaczana najpierw przez !! Python / tuple, a następnie w tym samym formacie co listy.

Ładowanie pliku yaml

Powiedzmy, że mam jeden plik yaml, który zawiera:

---
# An employee record
name: Raagvendra Joshi
job: Developer
skill: Oracle
employed: True
foods:
   - Apple
   - Orange
   - Strawberry
   - Mango
languages:
   Oracle: Elite
   power_builder: Elite
   Full Stack Developer: Lame
education:
   4 GCSEs
   3 A-Levels
   MCA in something called com

Teraz napiszmy kod, który załaduje ten plik yaml za pomocą funkcji yaml.load. Poniżej znajduje się kod tego samego.

Ponieważ dane wyjściowe nie wyglądają na czytelne, upiększam je, używając w końcu json. Porównaj otrzymane dane wyjściowe i rzeczywisty plik yaml, który mamy.

Wynik

Jednym z najważniejszych aspektów tworzenia oprogramowania jest debugowanie. W tej sekcji zobaczymy różne sposoby debugowania Pythona za pomocą wbudowanego debuggera lub debuggerów innych firm.

PDB - debuger języka Python

Moduł PDB obsługuje ustawianie punktów przerwania. Punkt przerwania to celowe wstrzymanie programu, w którym można uzyskać więcej informacji o stanie programów.

Aby ustawić punkt przerwania, wstaw linię

pdb.set_trace()

Przykład

pdb_example1.py
import pdb
x = 9
y = 7
pdb.set_trace()
total = x + y
pdb.set_trace()

W tym programie wstawiliśmy kilka punktów przerwania. Program zatrzyma się w każdym punkcie przerwania (pdb.set_trace ()). Aby wyświetlić zawartość zmiennych, po prostu wpisz nazwę zmiennej.

c:\Python\Python361>Python pdb_example1.py
> c:\Python\Python361\pdb_example1.py(8)<module>()
-> total = x + y
(Pdb) x
9
(Pdb) y
7
(Pdb) total
*** NameError: name 'total' is not defined
(Pdb)

Naciśnij przycisk c lub kontynuuj, aby kontynuować wykonywanie programów do następnego punktu przerwania.

(Pdb) c
--Return--
> c:\Python\Python361\pdb_example1.py(8)<module>()->None
-> total = x + y
(Pdb) total
16

Ostatecznie będziesz musiał debugować znacznie większe programy - programy, które używają podprogramów. Czasami problem, który próbujesz znaleźć, leży w podprogramie. Rozważmy następujący program.

import pdb
def squar(x, y):
   out_squared = x^2 + y^2
   return out_squared
if __name__ == "__main__":
   #pdb.set_trace()
   print (squar(4, 5))

Teraz po uruchomieniu powyższego programu

c:\Python\Python361>Python pdb_example2.py
> c:\Python\Python361\pdb_example2.py(10)<module>()
-> print (squar(4, 5))
(Pdb)

Możemy użyć ?aby uzyskać pomoc, ale strzałka wskazuje linię, która ma zostać wykonana. W tym momencie dobrze jest nacisnąć s dos wejść w tę linię.

(Pdb) s
--Call--
>c:\Python\Python361\pdb_example2.py(3)squar()
-> def squar(x, y):

To jest wywołanie funkcji. Jeśli chcesz zobaczyć, gdzie jesteś w swoim kodzie, wypróbuj l -

(Pdb) l
1 import pdb
2
3 def squar(x, y):
4 -> out_squared = x^2 + y^2
5
6 return out_squared
7
8 if __name__ == "__main__":
9 pdb.set_trace()
10 print (squar(4, 5))
[EOF]
(Pdb)

Możesz nacisnąć n, aby przejść do następnej linii. W tym momencie jesteś wewnątrz metody out_squared i masz dostęp do zmiennej zadeklarowanej wewnątrz funkcji .ie x i y.

(Pdb) x
4
(Pdb) y
5
(Pdb) x^2
6
(Pdb) y^2
7
(Pdb) x**2
16
(Pdb) y**2
25
(Pdb)

Widzimy więc, że operator ^ nie jest tym, czego chcieliśmy, zamiast tego musimy użyć operatora ** do zrobienia kwadratów.

W ten sposób możemy debugować nasz program wewnątrz funkcji / metod.

Logowanie

Moduł rejestrowania jest częścią biblioteki standardowej Pythona od wersji 2.3. Ponieważ jest to moduł wbudowany, wszystkie moduły Pythona mogą uczestniczyć w logowaniu, dzięki czemu nasz dziennik aplikacji może zawierać Twoją własną wiadomość zintegrowaną z wiadomościami z modułu zewnętrznego. Zapewnia dużą elastyczność i funkcjonalność.

Korzyści z logowania

  • Diagnostic logging - Rejestruje zdarzenia związane z działaniem aplikacji.

  • Audit logging - Zapisuje zdarzenia do analizy biznesowej.

Wiadomości są zapisywane i rejestrowane na poziomie „ważności” i minimalnym

  • DEBUG (debug()) - komunikaty diagnostyczne do rozwoju.

  • INFO (info()) - standardowe komunikaty „postęp”.

  • WARNING (warning()) - wykryto mniej poważny problem.

  • ERROR (error()) - napotkał błąd, prawdopodobnie poważny.

  • CRITICAL (critical()) - zwykle błąd krytyczny (program zatrzymuje się).

Przyjrzyjmy się poniższemu prostemu programowi,

import logging

logging.basicConfig(level=logging.INFO)

logging.debug('this message will be ignored') # This will not print
logging.info('This should be logged') # it'll print
logging.warning('And this, too') # It'll print

Powyżej rejestrujemy komunikaty na poziomie ważności. Najpierw importujemy moduł, wywołujemy basicConfig i ustawiamy poziom logowania. Poziom, który ustawiliśmy powyżej, to INFO. Następnie mamy trzy różne instrukcje: oświadczenie debugowania, oświadczenie informacyjne i oświadczenie ostrzegawcze.

Wyjście z logging1.py

INFO:root:This should be logged
WARNING:root:And this, too

Ponieważ instrukcja info znajduje się poniżej instrukcji debugowania, nie możemy zobaczyć komunikatu debugowania. Aby uzyskać instrukcję debugowania również w terminalu wyjściowym, wszystko, co musimy zmienić, to poziom basicConfig.

logging.basicConfig(level = logging.DEBUG)

Na wyjściu możemy zobaczyć,

DEBUG:root:this message will be ignored
INFO:root:This should be logged
WARNING:root:And this, too

Domyślne zachowanie oznacza również ostrzeżenie, jeśli nie ustawimy żadnego poziomu logowania. Po prostu zakomentuj drugą linię z powyższego programu i uruchom kod.

#logging.basicConfig(level = logging.DEBUG)

Wynik

WARNING:root:And this, too

Poziom rejestrowania wbudowany w Pythonie to w rzeczywistości liczby całkowite.

>>> import logging
>>>
>>> logging.DEBUG
10
>>> logging.CRITICAL
50
>>> logging.WARNING
30
>>> logging.INFO
20
>>> logging.ERROR
40
>>>

Możemy również zapisywać komunikaty dziennika do pliku.

logging.basicConfig(level = logging.DEBUG, filename = 'logging.log')

Teraz wszystkie komunikaty dziennika trafiają do pliku (logging.log) w bieżącym katalogu roboczym zamiast na ekranie. Jest to o wiele lepsze podejście, ponieważ pozwala nam na analizę postów otrzymanych wiadomości.

Możemy również ustawić datownik za pomocą naszego komunikatu dziennika.

logging.basicConfig(level=logging.DEBUG, format = '%(asctime)s %(levelname)s:%(message)s')

Wynik otrzyma coś takiego,

2018-03-08 19:30:00,066 DEBUG:this message will be ignored
2018-03-08 19:30:00,176 INFO:This should be logged
2018-03-08 19:30:00,201 WARNING:And this, too

Benchmarking

Benchmarking lub profilowanie to po prostu sprawdzenie, jak szybko wykonuje się kod i gdzie są wąskie gardła? Głównym powodem jest optymalizacja.

czas

Python zawiera wbudowany moduł o nazwie timeit. Możesz go użyć do odmierzania czasu małych fragmentów kodu. Moduł timeit korzysta z funkcji czasu specyficznych dla platformy, aby uzyskać możliwie najdokładniejsze czasy.

Dzięki temu możemy porównać dwie dostawy kodu pobranego przez każdą z nich, a następnie zoptymalizować skrypty, aby uzyskać lepszą wydajność.

Moduł timeit ma interfejs wiersza poleceń, ale można go również importować.

Istnieją dwa sposoby wywołania skryptu. Najpierw użyjmy skryptu, w tym celu uruchom poniższy kod i zobacz dane wyjściowe.

import timeit
print ( 'by index: ', timeit.timeit(stmt = "mydict['c']", setup = "mydict = {'a':5, 'b':10, 'c':15}", number = 1000000))
print ( 'by get: ', timeit.timeit(stmt = 'mydict.get("c")', setup = 'mydict = {"a":5, "b":10, "c":15}', number = 1000000))

Wynik

by index: 0.1809192126703489
by get: 0.6088525265034692

Powyżej używamy dwóch różnych metod .ie przez indeks dolny i uzyskujemy dostęp do wartości klucza słownika. Wykonujemy instrukcję 1 milion razy, ponieważ jest ona wykonywana zbyt szybko dla bardzo małych danych. Teraz widzimy, że dostęp do indeksu jest znacznie szybszy w porównaniu do get. Możemy uruchomić kod wielokrotnie, a czas wykonania będzie nieznaczny, aby uzyskać lepsze zrozumienie.

Innym sposobem jest uruchomienie powyższego testu w linii poleceń. Zróbmy to,

c:\Python\Python361>Python -m timeit -n 1000000 -s "mydict = {'a': 5, 'b':10, 'c':15}" "mydict['c']"
1000000 loops, best of 3: 0.187 usec per loop

c:\Python\Python361>Python -m timeit -n 1000000 -s "mydict = {'a': 5, 'b':10, 'c':15}" "mydict.get('c')"
1000000 loops, best of 3: 0.659 usec per loop

Powyższe dane wyjściowe mogą się różnić w zależności od sprzętu systemowego i wszystkich aplikacji aktualnie uruchomionych w systemie.

Poniżej możemy skorzystać z modułu timeit, jeśli chcemy wywołać funkcję. Ponieważ możemy dodać wiele instrukcji wewnątrz funkcji do przetestowania.

import timeit

def testme(this_dict, key):
   return this_dict[key]

print (timeit.timeit("testme(mydict, key)", setup = "from __main__ import testme; mydict = {'a':9, 'b':18, 'c':27}; key = 'c'", number = 1000000))

Wynik

0.7713474590139164