Python orientato agli oggetti - Serializzazione degli oggetti

Nel contesto dell'archiviazione dei dati, la serializzazione è il processo di traduzione delle strutture dati o dello stato dell'oggetto in un formato che può essere memorizzato (ad esempio, in un file o un buffer di memoria) o trasmesso e ricostruito in un secondo momento.

Nella serializzazione, un oggetto viene trasformato in un formato che può essere memorizzato, in modo da poterlo deserializzare successivamente e ricreare l'oggetto originale dal formato serializzato.

Salamoia

Il pickling è il processo mediante il quale una gerarchia di oggetti Python viene convertita in un flusso di byte (di solito non leggibile dall'uomo) da scrivere in un file, noto anche come serializzazione. Unpickling è l'operazione inversa, in base alla quale un flusso di byte viene riconvertito in una gerarchia di oggetti Python funzionante.

Pickle è il modo più semplice dal punto di vista operativo per memorizzare l'oggetto. Il modulo Python Pickle è un modo orientato agli oggetti per memorizzare gli oggetti direttamente in uno speciale formato di archiviazione.

Cosa può fare?

  • Pickle può memorizzare e riprodurre dizionari ed elenchi molto facilmente.
  • Memorizza gli attributi degli oggetti e li ripristina nello stesso stato.

Quale sottaceto non può fare?

  • Non salva il codice di un oggetto. Solo i valori degli attributi.
  • Non può memorizzare handle di file o socket di connessione.

In breve, possiamo dire che il pickling è un modo per archiviare e recuperare variabili di dati dentro e fuori da file in cui le variabili possono essere liste, classi, ecc.

Per decapare qualcosa devi -

  • sottaceto di importazione
  • Scrivi una variabile su file, qualcosa di simile
pickle.dump(mystring, outfile, protocol),

dove il protocollo del terzo argomento è opzionale Per deselezionare qualcosa devi:

Importa sottaceti

Scrivi una variabile in un file, qualcosa di simile

myString = pickle.load(inputfile)

Metodi

L'interfaccia pickle fornisce quattro metodi diversi.

  • dump() - Il metodo dump () serializza in un file aperto (oggetto simile a un file).

  • dumps() - Serializza in una stringa

  • load() - Deserializza da un oggetto di tipo aperto.

  • loads() - Deserializza da una stringa.

Sulla base della procedura di cui sopra, di seguito è riportato un esempio di "decapaggio".

Produzione

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.'

Quindi, nell'esempio sopra, abbiamo creato un'istanza di una classe Cat e poi l'abbiamo decapata, trasformando la nostra istanza "Cat" in un semplice array di byte.

In questo modo possiamo facilmente memorizzare l'array di byte su un file binario o in un campo di database e ripristinarlo alla sua forma originale dal nostro supporto di archiviazione in un secondo momento.

Inoltre se vuoi creare un file con un oggetto decapato, puoi usare il metodo dump () (al posto del dump * () * one) passando anche un file binario aperto e il risultato del decapaggio verrà memorizzato nel file automaticamente.

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

Unpickling

Il processo che prende un array binario e lo converte in una gerarchia di oggetti è chiamato unpickling.

Il processo di deselezione viene eseguito utilizzando la funzione load () del modulo pickle e restituisce una gerarchia di oggetti completa da un semplice array di byte.

Usiamo la funzione di caricamento nel nostro esempio precedente.

Produzione

MeOw is black
Pussy is white

JSON

JSON (JavaScript Object Notation) fa parte della libreria standard Python è un formato di scambio dati leggero. È facile per gli esseri umani leggere e scrivere. È facile da analizzare e generare.

A causa della sua semplicità, JSON è un modo con cui archiviamo e scambiamo dati, che si ottiene attraverso la sua sintassi JSON e viene utilizzato in molte applicazioni web. Poiché è in formato leggibile dall'uomo, e questo può essere uno dei motivi per utilizzarlo nella trasmissione dei dati, oltre alla sua efficacia quando si lavora con le API.

Un esempio di dati in formato JSON è il seguente:

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

Python semplifica il lavoro con i file Json. Il modulo utilizzato per questo scopo è il modulo JSON. Questo modulo dovrebbe essere incluso (integrato) nella tua installazione di Python.

Quindi vediamo come possiamo convertire il dizionario Python in JSON e scriverlo in un file di testo.

Da JSON a Python

Leggere JSON significa convertire JSON in un valore (oggetto) Python. La libreria json analizza JSON in un dizionario o in un elenco in Python. Per fare ciò, usiamo la funzione load () (carica da una stringa), come segue:

Produzione

Di seguito è riportato un file json di esempio,

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

Sopra il contenuto (Data1.json) sembra un dizionario convenzionale. Possiamo usare pickle per memorizzare questo file ma il suo output non è leggibile dall'uomo.

JSON (Java Script Object Notification) è un formato molto semplice e questo è uno dei motivi della sua popolarità. Ora esaminiamo l'output json tramite il programma seguente.

Produzione

Sopra apriamo il file json (data1.json) per la lettura, otteniamo il gestore di file e passiamo a json.load e recuperiamo l'oggetto. Quando proviamo a stampare l'output dell'oggetto, è uguale al file json. Sebbene il tipo di oggetto sia dizionario, risulta come un oggetto Python. Scrivere al json è semplice come abbiamo visto questo sottaceto. Sopra carichiamo il file json, aggiungiamo un'altra coppia di valori chiave e la riscriviamo nello stesso file json. Ora, se vediamo data1.json, sembra diverso .ie non nello stesso formato che abbiamo visto in precedenza.

Per fare in modo che il nostro output abbia lo stesso aspetto (formato leggibile dall'uomo), aggiungi la coppia di argomenti nella nostra ultima riga del programma,

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

Allo stesso modo come pickle, possiamo stampare la stringa con dump e caricarla con i carichi. Di seguito è riportato un esempio di ciò,

YAML

YAML può essere lo standard di serializzazione dei dati più umano per tutti i linguaggi di programmazione.

Il modulo Python yaml si chiama pyaml

YAML è un'alternativa a JSON -

  • Human readable code - YAML è il formato più leggibile dall'uomo, tanto che anche il suo contenuto in prima pagina viene visualizzato in YAML per chiarire questo punto.

  • Compact code - In YAML usiamo il rientro degli spazi bianchi per indicare la struttura e non le parentesi.

  • Syntax for relational data - Per i riferimenti interni utilizziamo ancore (&) e alias (*).

  • One of the area where it is used widely is for viewing/editing of data structures - ad esempio file di configurazione, dumping durante il debug e intestazioni dei documenti.

Installazione di YAML

Poiché yaml non è un modulo integrato, è necessario installarlo manualmente. Il modo migliore per installare yaml su una macchina Windows è tramite pip. Esegui sotto il comando sul tuo terminale Windows per installare yaml,

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

Quando si esegue il comando sopra, lo schermo mostrerà qualcosa di simile sotto in base a qual è l'ultima versione corrente.

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

Per provarlo, vai alla shell Python e importa il modulo yaml, importa yaml, se non viene trovato alcun errore, allora possiamo dire che l'installazione è andata a buon fine.

Dopo aver installato pyaml, diamo un'occhiata al codice sottostante,

script_yaml1.py

Sopra abbiamo creato tre diverse strutture dati, dizionario, elenco e tupla. Su ciascuna struttura, eseguiamo yaml.dump. Il punto importante è come l'output viene visualizzato sullo schermo.

Produzione

L'output del dizionario sembra pulito .ie. chiave: valore.

Spazio bianco per separare oggetti diversi.

L'elenco è annotato con trattino (-)

La tupla è indicata prima con !! Python / tuple e poi nello stesso formato delle liste.

Caricamento di un file yaml

Quindi diciamo che ho un file yaml, che contiene,

---
# 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

Ora scriviamo un codice per caricare questo file yaml tramite la funzione yaml.load. Di seguito è riportato il codice per lo stesso.

Poiché l'output non sembra molto leggibile, alla fine lo abbellisco usando json. Confronta l'output ottenuto con il file yaml effettivo che abbiamo.

Produzione

Uno degli aspetti più importanti dello sviluppo del software è il debug. In questa sezione vedremo diversi modi di debug di Python con debugger integrato o debugger di terze parti.

PDB - Il debugger Python

Il modulo PDB supporta l'impostazione dei punti di interruzione. Un punto di interruzione è una pausa intenzionale del programma, in cui è possibile ottenere maggiori informazioni sullo stato del programma.

Per impostare un punto di interruzione, inserisci la riga

pdb.set_trace()

Esempio

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

Abbiamo inserito alcuni punti di interruzione in questo programma. Il programma si fermerà ad ogni breakpoint (pdb.set_trace ()). Per visualizzare il contenuto di una variabile è sufficiente digitare il nome della variabile.

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)

Premere c o continuare con l'esecuzione dei programmi fino al punto di interruzione successivo.

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

Alla fine, sarà necessario eseguire il debug di programmi molto più grandi, programmi che utilizzano subroutine. E a volte, il problema che stai cercando di trovare risiede all'interno di una subroutine. Considera il seguente programma.

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))

Ora eseguendo il programma sopra,

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

Possiamo usare ?per ottenere aiuto, ma la freccia indica la linea che sta per essere eseguita. A questo punto è utile premere s as per entrare in quella linea.

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

Questa è una chiamata a una funzione. Se vuoi una panoramica di dove ti trovi nel codice, prova 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)

Puoi premere n per passare alla riga successiva. A questo punto sei all'interno del metodo out_squared e hai accesso alla variabile dichiarata all'interno della funzione .ie x e y.

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

Quindi possiamo vedere che l'operatore ^ non è quello che volevamo, invece dobbiamo usare l'operatore ** per fare i quadrati.

In questo modo possiamo eseguire il debug del nostro programma all'interno delle funzioni / metodi.

Registrazione

Il modulo di registrazione fa parte della libreria standard di Python dalla versione 2.3 di Python. Poiché è un modulo integrato, tutti i moduli Python possono partecipare alla registrazione, in modo che il nostro registro dell'applicazione possa includere il tuo messaggio integrato con i messaggi del modulo di terze parti. Fornisce molta flessibilità e funzionalità.

Vantaggi della registrazione

  • Diagnostic logging - Registra gli eventi relativi al funzionamento dell'applicazione.

  • Audit logging - Registra eventi per analisi aziendali.

I messaggi vengono scritti e registrati a livelli di "gravità" e minu

  • DEBUG (debug()) - messaggi diagnostici per lo sviluppo.

  • INFO (info()) - messaggi standard di “avanzamento”.

  • WARNING (warning()) - rilevato un problema non grave.

  • ERROR (error()) - riscontrato un errore, forse grave.

  • CRITICAL (critical()) - di solito un errore fatale (il programma si interrompe).

Diamo un'occhiata al seguente semplice programma,

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

Sopra stiamo registrando i messaggi a livello di gravità. Per prima cosa importiamo il modulo, chiamiamo basicConfig e impostiamo il livello di registrazione. Il livello che abbiamo impostato sopra è INFO. Quindi abbiamo tre diverse istruzioni: dichiarazione di debug, dichiarazione di informazioni e una dichiarazione di avviso.

Output di logging1.py

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

Poiché l'istruzione info è sotto l'istruzione debug, non siamo in grado di vedere il messaggio di debug. Per ottenere anche l'istruzione di debug nel terminale di output, tutto ciò che dobbiamo modificare è il livello basicConfig.

logging.basicConfig(level = logging.DEBUG)

E nell'output possiamo vedere,

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

Anche il comportamento predefinito significa che se non impostiamo alcun livello di registrazione viene visualizzato un avviso. Commenta semplicemente la seconda riga del programma sopra ed esegui il codice.

#logging.basicConfig(level = logging.DEBUG)

Produzione

WARNING:root:And this, too

I livelli di registrazione incorporati in Python sono in realtà numeri interi.

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

Possiamo anche salvare i messaggi di log nel file.

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

Ora tutti i messaggi di registro andranno nel file (logging.log) nella directory di lavoro corrente invece che sullo schermo. Questo è un approccio molto migliore in quanto ci consente di analizzare i post dei messaggi che abbiamo ricevuto.

Possiamo anche impostare il timbro della data con il nostro messaggio di registro.

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

L'output otterrà qualcosa del tipo,

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

Analisi comparativa

Il benchmarking o la profilazione servono fondamentalmente a testare la velocità di esecuzione del codice e dove sono i colli di bottiglia? Il motivo principale per farlo è per l'ottimizzazione.

timeit

Python viene fornito con un modulo integrato chiamato timeit. Puoi usarlo per cronometrare piccoli frammenti di codice. Il modulo timeit utilizza funzioni temporali specifiche della piattaforma in modo da ottenere i tempi più precisi possibili.

Quindi, ci consente di confrontare due spedizioni di codice prese da ciascuna e quindi ottimizzare gli script per ottenere prestazioni migliori.

Il modulo timeit ha un'interfaccia a riga di comando, ma può anche essere importato.

Esistono due modi per richiamare uno script. Usiamo prima lo script, per eseguire il codice seguente e vedere l'output.

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))

Produzione

by index: 0.1809192126703489
by get: 0.6088525265034692

Sopra usiamo due diversi metodi .ie per pedice e arriviamo ad accedere al valore della chiave del dizionario. Eseguiamo l'istruzione 1 milione di volte poiché viene eseguita troppo velocemente per dati molto piccoli. Ora possiamo vedere l'accesso all'indice molto più velocemente rispetto a get. Possiamo eseguire il codice molte volte e ci sarà una leggera variazione nel tempo di esecuzione per ottenere una migliore comprensione.

Un altro modo è eseguire il test precedente nella riga di comando. Facciamolo,

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

L'output di cui sopra può variare in base all'hardware del sistema e alle applicazioni attualmente in esecuzione nel sistema.

Di seguito possiamo usare il modulo timeit, se vogliamo chiamare una funzione. Poiché possiamo aggiungere più istruzioni all'interno della funzione da testare.

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))

Produzione

0.7713474590139164