Serializzazione di oggetti

A volte abbiamo bisogno di salvare un oggetto sul disco per recuperarlo in un secondo momento, oppure può essere necessario inviare un oggetto attraverso la rete, a un altro programma Python in esecuzione su un’altra macchina.
Il processo di trasformare lo stato di un oggetto in un formato in grado che si possa memorizzare, recuperare e trasportare è conosciuto come serializzazione o marshalling.
In Python abbiamo diversi moduli che facilitano questo compito, come marshal, pickle, cPickle e shelve.
Moduli
Il modulo marshal è il più semplice e il più primitivo dei tre, e il suo scopo primario e la sua ragione di essere non è quella della serializzare degli oggetti, ma di lavorare con il bytecode di Python (file con estensione .pyc).
marshal permette serializzare solo oggetti semplici (la maggior parte dei tipi inclusi di default in Python), e non fornisce alcun meccanismo di sicurezza o di controlli a fronte di dati corrotti o non correttamente formattato. Inoltre, il formato usato per salvare il bytecode (e quindi il formato usato per memorizzare gli oggetti con marshal) può cambiare tra versioni, quindi non è adatto per la memorizzazione dati a lungo termine.
pickle, per parte sua, è in grado di serializzare quasi tutti gli oggetti (oggetti di tipi definiti dall’utente, collezioni contenenti collezioni, ecc) e ha alcuni meccanismi di sicurezza di base. Tuttavia, per essere più complesso di marshal, e, soprattutto, essendo scritto in Python al posto di C, come marshal, è anche molto lento.
La soluzione, se la velocità di serializzazione è importante per la nostra applicazione, è di utilizzare cPickle, ch’è un’implementazione in C di pickle. cPickle è fino a 1000 volte più veloce di pickle, e quasi veloce come marshal.
Se si tenta di importare cPickle e si produce un errore per qualche motivo, viene generata un’eccezione di tipo ImportError. Per utilizzare cPickle s’è disponibile e pickle altrimenti potremmo usare un codice simile al seguente:
         		try:
         		    import cPickle as pickle
         		except ImportError:
         		    import pickle
as in un import serve per importare l’elemento selezionato utilizzando un nome diverso, invece del suo nome.
Il modo più semplice per serializzare un oggetto utilizzando pickle è attraverso una chiamata a la funzione dump passando come argomento l’oggetto da serializzare e un oggetto file dove lo si salva (o qualsiasi altro oggetto simile a un file sempre che offra dei metodi di read, realine e write).
         		try:
         		    import cPickle as pickle
         		except ImportError:
         		    import pickle
         		
         		mio_file = file("dati.dat", "w")
         		animali = ["pitone", "mono", "camello"]
         		
         		pickle.dump(animali, mio_file)
         		
         		mio_file.close()
La funzione dump ha anche un parametro opzionale protocol che indica il protocollo da utilizzare durante il salvataggio. Il valore di default è 0, che utilizza il formato di testo ed è il meno efficiente. Il protocollo 1 è più efficiente di 0 ma inferiore a 2. Il protocollo 1 e 2 utilizzano un formato binario per memorizzare i dati.
         		try:
         		    import cPickle as pickle
         		except ImportError:
         		    import pickle
         		
         		mio_file = file("dati.dat", "w")
         		animali = ["pitone", "mono", "camello"]
         		
         		pickle.dump(animali, mio_file, 2)
         		
         		mio_file()
Per ricaricare un oggetto serializzato si utilizza la funzione load, che viene passato il file che si è salvato.
         		try:
         		    import cPickle as pickle
         		except ImportError:
         		    import pickle
         		
         		mio_file = file("dati.dat", "w")
         		animali = ["pitone", "mono", "camello"]
         		
         		pickle.dump(animali, mio_file)
         		
         		mio_file.close()
         		
         		mio_file = file("dati.dat")
         		
         		animali2 = pickle.load(mio_file)
         		print animali2
Ora supponiamo di voler archiviare un paio di liste in un file. Questo sarebbe così semplice come chiamare una volta a dump, per ogni lista, e quindi chiamare una volta load per ogni lista.
         		mio_file = file("dati.dat", "w")
         		animali = ["pitone", "mono", "camello"]
         		linguaggi = ["python", "mono", "perl"]
         		
         		pickle.dump(animali, mio_file)
         		pickle.dump(linguaggi, mio_file)
         		
         		mio_file = file("dati.dat")
         		
         		animali2 = pickle.load(mio_file)
         		linguaggi2 = pickle.load(mio_file)
         		print animali2
         		print linguaggi2
Ma cosa succederebbe se avessimo salvato 30 oggetti e volessimo accedere all’ultimo? Oppure, se ci ricordiamo in quale posizione l’ avevamo salvato? Il modulo shelve estende pickle/cPickle per fornire un modo per eseguire la serializzazione in modo più chiaro e semplice, in cui saremo in grado di accedere alla versione serializzata di un oggetto attraverso una stringa associata, simile ad una struttura come un dizionario.
L’unica funzione ch’è necessario conoscere dal modulo shelve è open, che conta con un parametro filename per indicare il percorso di un file in cui memorizzare gli oggetti (si può effettivamente creare più di un file, con nomi basati su filename, ma questo è trasparente per l’utente).
La funzione open ha anche un parametro opzionale protocol, con la quale specificare il protocollo che si desidera utilizzare al di sotto con pickle.
Come risultato della chiamata a open si ottiene un oggetto Shelf, con il quale possiamo lavorare come se si trattasse di un normale dizionario (a eccezione che le chiavi possono essere solo stringhe) per memorizzare e recuperare i nostri oggetti.
Come un dizionario qualsiasi la classe Shelf ha dei metodi come get, has_key, items, keys, values, …
Una volta che abbiamo terminato di lavorare con l’oggetto Shelf, lo chiudiamo con il metodo close.
         		import shelve
         
         		animali = ["pitone", "mono", "camello"]
         		linguaggi = ["python", "mono", "perl"]
         		
         		shelf = shelve.open("dati.dat")
         		shelf["prima"] = animali
         		shelf["seconda"] = linguaggi
         		
         		print shelf["seconda"]
         		
         		shelf.close()


Similari
Fondamentali di jQuery
232% JQuery
jQuery stà diventando rapidamente uno strumento che ogni sviluppatore web di interfacce dovrebbe conoscere. Lo scopo di questo libro è di fornire una panoramica della biblioteca, in modo che qu…
Guida allo Zend Framework
106% Zend
Zend Framework è un framework open source per PHP. Zend Framework separa la logica e le azioni usando il pattern MVC (Model View Controller). Cosa è lo Zend Framework? Framework per la costruzione di siti web più veloci e …
Modi di fare e di non fare in Python
89% Python
Questo documento può essere considerato un compagno del tutorial di Python. Viene illustrato come utilizzare Python, e quasi ancora più importante, come non usare Python. [expand title=”Costrutti del linguaggio che non dov…
Funzioni popolari per gestire le stringhe
71% Php
PHP ha una vasta scelta di funzioni integrate per la gestione delle stringhe che permettono di manipolarle facilmente in quasi ogni modo possibile. Tuttavia, imparare tutte queste funzioni, ricordando quello che fanno e qu…
Introduzione al PHP
43% Php
Scopri ed esplora la programmazione di scripting server side con il linguaggio PHP. Questo post è rivolto a persone che sono nuovi alla programmazione. Non è adatto a persone che già hanno competenze di programmazione di b…