Persistence

3 06 2007

PythonComment rendre les variables du code persistentes à travers le temps et les pannes de courants en passant par les crashs d’application ?

Cette problèmatique fut mise en avant lors du développement d’ECS, un framework e-commerce écrit en Python, au sein d’Emencia, société de services en logiciels libres.

Les modules Python pickle et cPickle servent à cela, mais leurs mise en place de manière générique peuvent etre coûteuse et de plus comment centraliser des centaines d’objets à un moment T donné ?

ECS grâce au projet SQLAchemy, supporte tous types de bases données et fournis en plus un tas de fonctions pour manipuler des tables en base de donnée à partir d’un modèle de code. C’est donc à partir de la que fut developpé le modèle de persistence.

Le modèle de persistence écrit pour ECS, fournit donc les outils pour effectuer la sauvegarde de tout objet instancié au sein de Python. Il contient en plus une implémentation rapide par métaclasse pour accélérer l’intégration au sein du code.

Voici un exemple d’implémentation de classe persistente, prenons l’exemple d’un chat :

from persistency import PersistentClass

class Cat(object):
  __metaclass__ = PersistentClass
  age = None
  name = None

def __init__(self, name='', age=-1):
  self.age = age
  self.name = name
  if self.age == -1:
    self.load()
  else:
    self.save()

def database(cls):
  return 'sqlite:///:memory:'

Cat._sqluri_callback = database

Nous allons donc créer un chat du nom de Felix agé de 8 ans.

felix = Cat('Felix', 8)
# Roooh il est beau ce chat !


Malheureusement Felix meurt lors d’une messe noire :(

del felix
# Oh non c'est terrible !

Heureusement comme tout le monde le sait, les chats ont neuf vies et Felix n’est pas mort !
Hourra pour Felix !!!

felix_is_not_dead = Cat('Felix')
felix_is_not_dead.age

Ce qui affichera au final 8.

La métaclasse permet de sauvegarder tout les attributs d’objet, excluant ceux commencant par un ‘_’ comme pour les attributs privés. La sauvegarde des attributs de l’objet se fais au format JSON, ce qui permet la visualisation de chaques objets sauvegardés à partir d’un autre language.

Dans les métaclasses, on peut aussi ajouter des attributs et des méthodes qui vont s’ajouter à l’état et à l’interface des classes instanciées. Ce seront donc des attributs et des méthodes de classe. Dans notre cas, nous allons ajouter les méthodes save, load, delete.

class PersistentClass(type):
    def __new__(clsbase, name, bases, dic):
            """Turns the given class into a persistent one.
            By adding a wrapped SQL mapper
            "
""
            if '_sqluri_callback' not in dic:
                dic['_sqluri_callback'] = getBaseForPersistence

            def _get_persistence(cls):
                """Return the persistence"""
                return Persistence(sqluri_callback=cls._sqluri_callback,
                                   wrapper=GenericWrapper,
                                   table=cls.__class__.__name__.lower())
            dic['_get_persistence'] = _get_persistence

            def save(cls):
                """Saves into the DB"""
                persistence = cls._get_persistence()
                cls_wrapped = GenericWrapper(cls)

                persistence.delete(cls_wrapped.id)
                persistence.save(cls_wrapped)
            dic['save'] = save

            def delete(cls):
                """Deletes into the DB"""
                cls._get_persistence().delete(GenericWrapper(cls).id)
            dic['delete'] = delete

            def load(cls):
                """Loads from the DB."""
                wrapper = cls._get_persistence().load(cls.name)

                if wrapper is not None:
                    wrapper._load(cls)

            dic['load'] = load

            return type(name, bases, dic)

SVN du projet : http://svn.emencia.net/public


Actions

Informations

5 réponses à “Persistence”

4 06 2007
Alex (13:04:55) :

Pour les transactions et les sous-objets stoqués persistent dans la transaction vous faites comment ?

4 06 2007
Fantomas (13:21:09) :

Il suffit de rendre ces mêmes objets persistent, en implémentant le mécanisme de sauvegarde aux endroits necessaires dans les méthode de cet objet.

4 06 2007
Alex (16:52:05) :

Tu aurai un exemple stp ?

4 06 2007
Fantomas (19:46:15) :

Pose moi un use case.

5 06 2007
Maxime (21:51:04) :

Julien on voit que tu es a font dans tes codes! Je dirais meme plus tu vis ton code !! (lol)
Merci pour cette petite démo Python un jour peut etre je pourrais faire ce genre de chose …
Remarque avec un prof comme j’ai y’a pas de raisons …
Je ne te remercierai jamais asser Julien(joublierai pas)
;)

Laisser un commentaire

Vous pouvez utiliser ces balises html : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>