Magazine

python et la sérialisation

Publié le 29 avril 2008 par Mikebrant

Un bien grand mot pour pas grand chose.
Derrière ce dernier se trouve un concept simple à comprendre (enfin peut-être pas pour tous, faut pas pousser non plus).

La sérialisation consiste à sauvegarder l'état d'un objet
Ca peut être très utile,par exemple,pour sauver l'état d'un objet  à la fermeture d'un programme, et à sa réouverture, on charge l'objet pour avoir la config précédente.
Néanmoins,le problème majeur est qu'il ne faut pas modifier les attributs et méthodes d'une classe que l'on souhaite sauver; pour des raisons évidentes .
On va voir 2 modules: cPickle,puis shelve.

cPickle

cPickle ne peut pas sérialiser tous les objets :
-les Threads et les Sockets
-les Sextoys
-et bien d'autres.
Ils sont dit unpickables.
Dans cette partie , on va tout d'abord voir les fonctions permettant de sérialiser un seul objet par flux(fichier/variable) puis les classes de cPickle qui permettent quant à elles de sérialiser plusieurs objets dans un même flux(fichier) .

Les fonctions du module cPickle

Il a 2 types de fonctions:
dump() et load() qui dé/sérialisent via un fichier
dumps() et loads() qui dé/sérialisent via un string

dump() et load()

dump():

squelette: dump(Objet,Fichier[,protocole])->rien
Cette fonction sert donc à sérialiser notre objet dans l'objet de type fichier.

load():

squelette: load(Fichier)->Objet
Cette fonction va donc utiliser l'objet Fichier pour retouner l'objet.
Un petit exemple:

#-*- coding:Utf-8 -*-
import cPickle

monFichier=open('monFichier','w')

maListe=dir(cPickle)
cPickle.dump(maListe,monFichier)
monFichier.close()
maNouvelleListe=cPickle.load( open( 'monFichier','r' ) )
print maNouvelleListe


Dans cet exemple,
On crée un Objet de type fichier, avec l'accès en écriture. On utilise dump(), qui va sérialiser
l'objet maListe dans le fichier monFichier.
maNouvelleListe va donc contenir l'objet sérialisé(maListe).

dumps() et loads():

dumps():

squelette: dumps(Objet[,protocole])->String
Cette fonction sert donc à sérialiser notre objet dans une chaine qu'il retourne.

loads():

squelette: load(String[,protocole])->Objet
Cette fonction va donc utiliser une chaine pour retouner l'objet qu'elle contient.
Et l'exemple:

#-*- coding:Utf-8 -*-
import cPickle
maListe=dir(cPickle)
maChaine=cPickle.dumps(maListe)
maNouvelleListe=cPickle.loads(maChaine)

print maNouvelleListe


Dans cet exemple,
On crée une liste. On utilise dumps(), qui va sérialiser l'objet maListe dans la chaine maChaine.
maNouvelleListe va donc contenir l'objet sérialisé(maListe)
.
Voilà, on a vu les fonctions de cPickle nous permettant de dé/sérialiser des objets, maintenant on va voir la classe Pickler et Unpickler

Les classes du module cPickle

On va utiliser 2 classes:
la classe Pickler qui permet de sérialiser un ou plusieurs objets dans le même flux,
la classe Unpickler qui désérialise ces objets.

Pickler(fichier[,protocole])

La classe s'instancie en prenant en paramètre obligatoire un objet de type fichier.
On va voir une seule méthode,parce que je commence à fatiguer:
dump().
squelette: dump(Objet)->rien
Cette méthode sérialise l'objet dans le fichier.Pour sérialiser plus objets dans le même fichier(même flux), il suffit de l'appeler plusieurs fois.

Unpickler(fichier)

La classe s'instancie en prenant,quant à elle, comme seul paramètre un objet de type fichier. On va utiliser là aussi une seule méthode pour désérialiser:
load().
squelette: load()->Objet
La méthode va retourner l'objet à partir du fichier(du flux) qu'elle va lire.
Pour retourner plusieurs objets contenu dans le même fichier(flux), il suffit de l'appeler plusieurs fois.
Et l'exemple:

#-*- coding:Utf-8 -*-
import cPickle
from cPickle import Pickler,Unpickler
def serialiser(maListe):
  """Va sérialiser tous les objets présents dans maListe dans un fichier"""
  monFichier=open('monFlux','w')
  pickler=Pickler(monFichier)
  for monObjet in maListe:
  pickler.dump(monObjet)

  print( str( monObjet ) +' est sérialisé' )
  monFichier.close()
def deserialiser():
  """va désérialiser tous les objets dans maNouvelleListe"""
  maNouvelleListe=[]
  depickler=Unpickler(open('monFlux','r'))
  yenA=True

  while yenA:
  try:
  maNouvelleListe.append(depickler.load())
  print('Désérialisé')
   except EOFError ,e:
  print'yen a plus'
   yenA=False
  return maNouvelleListe
serialiser(dir(cPickle))
jeVaisVousDeserialiser=deserialiser()
print jeVaisVousDeserialiser


On crée la fonction serialiser(maListe) ,laquelle va sérialiser des objets dans un même fichier(flux).
On crée un objet de type fichier,monFichier.
On instancie ensuite la classe Pickler, en passant en paramètremonFichier
fraichement créé.
Chaque objet présent dans maListe,va être sérialiser via notre objet pickler et sa méthode dump.
Enfin on ferme monFichier.

On crée ensuite la fonction deserialiser(), qui va désérialiser tous les objets présents dans le même fichier(même flux)
On instancie Unpickler,en passant en paramètre, notre fichier, avec les droits de lecture,evidemment.
A présent, tant que notre booléen yenA vaut True, on essaye d'ajouter dans maNouvelleListe ,un objet que l'on désérialise via depickler.
Si l'exception EOFerror survient, alors tous les objets présents dans le fichier(flux) ont été désérialisés.
On arrête alors la boucle,et on retourne notre nouvelleListe contenant les objets désérialisés.
Maintenant place au shell.

Shelve

Shelve fournit un système de base de données fichier s'utilisant comme les dictionnaires et permettant d'y stocker nos objets.
La base de données fichierque va utiliser Shelve est choisi automatiquement en fonction de l'OS,des paquets installés,blablabla,on s'en fout.
La seule fonction que vous avez besoin de connaitre est:open()

open()

squelette:
open(fichier [drapeau,protocole,writeback])->rien
Oula, ca fait pas mal de paramètres, on va voir à quoi ils servent...enfin essayer hein(j'ai déjà pas réussi à traduire writeback alors bon ca commence bien ....)
fichier:Alors lui, il est sert à ouvrir(ou accessoirement à ouvrir et créer...et ouais c'est la classe) une base de donnéefichier.
Ah oui, alors les bases de données fichier on les appelle des dictionnaires persistents.
Pourquoi ? tout simplement parce qu'on les utilise comme des dictionnaires et qu'ils prennent du persil de temps en temps... (ou accessoirement(j'aime bien ce mot) parce que ce sont des BDD donc durables)
drapeau:Peut avoir trois valeurs: bleu,blanc ou rouge...
Le flag représente les droits que nous avons sur fichier:
c:lecture/écriture et crée le 'dictionnaire persistent' si ce dernier n'existe pas,par défaut
r:lecture
w:ecriture
protocole:Si vous avez suivi, vous avez du le voir,à plusieurs reprises,je l'ai zappé parce que j'ai pas trop compris à quoi il servait , donc si une âme charitable voudrait bien me l'expliquer.
Ici il vaut par défaut None, dans toute la partie cPickle, il vaut par défaut 0.
writeback:Par défaut à False.
Si l'on veut mettre en cache tous les éléments modifiables de notre dictionnaire persistent,lequel les copiera dedans avant de se fermer.
S'il est à True on peut alors utiliser la fonction sync() qui va forcer à écrire les éléments du cache dans le dictionnaire et vider le cache.
Et l'exemple:

#-*- coding:Utf-8 -*-
import shelve
maBDD=shelve.open('maBDD')
for element in dir(shelve):
   maBDD[element]=getattr(shelve,element).__doc__
for element in maBDD:
  print maBDD[element]


Dans cet exemple,
On importe le module shelve.
On ouvre le dictionnaire persistent maBDD, et
chaque element contenu dans la liste sera la clef du dictionnaire persistent maBDD et aura pour valeur sa doc.
Voilà le billet est fini.Si vous avez des remarques n'hésitez pas.
dir(monObjet):retourne une liste contenant les attributs de monObjet.
getattr(monObjet,monNom):retourne l'attribut monNom de l'objet monObjet.
monElement.__doc__:retourne la doc de monElement.


Retour à La Une de Logo Paperblog

A propos de l’auteur


Mikebrant 9 partages Voir son profil
Voir son blog

l'auteur n'a pas encore renseigné son compte l'auteur n'a pas encore renseigné son compte