IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Sauvegarde d'objets et fichier de configuration


Sujet :

Python

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2011
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 15
    Points : 8
    Points
    8
    Par défaut Sauvegarde d'objets et fichier de configuration
    Bonjour à tous !

    j'ai une requête à vous soumettre concernant la sauvegarde d'objets dans un fichier de configuration texte. J'ai en effet un programme créant plusieurs objets, ayant pour attributs notamment, des listes d'objets, en plus d'int, string, etc. et je souhaiterais sauvegarder ces objets dans un fichier de configuration texte, de type .ini comme:

    [section1]
    obj1=nom
    obj1_attributs=attribut1,attribut2

    [section2]
    obj2=type
    obj2=attributs_obj2, nom_obj1, etc.
    ou dans un fichier XML, ou au format JSON.

    J'ai vu qu'il existait configparser, mais ma question serait plus de connaître les méthodes pour passer efficacement les objets existants à une version texte, et ensuite comment les lire et les recréer en fonction de leur type?

    merci d'avance,
    Silvio

  2. #2
    Expert éminent
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    3 824
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 3 824
    Points : 7 120
    Points
    7 120
    Par défaut
    J'ai peut-être pas tout saisi, mais ça ressemble a de la sérialisation et dans ce cas voir du côté de pickle
    Celui qui trouve sans chercher est celui qui a longtemps cherché sans trouver.(Bachelard)
    La connaissance s'acquiert par l'expérience, tout le reste n'est que de l'information.(Einstein)

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2011
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 15
    Points : 8
    Points
    8
    Par défaut
    ça pourrait ressembler à de la serialization effectivement. Mais il me manque quelques exemples concrets
    Sinon il me semblait que Pickle n'enregistrait qu'en binaire...

  4. #4
    Expert éminent
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 462
    Points : 9 249
    Points
    9 249
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Tant qu'il s'agit d'objet Python de base (int, float, list, tuple, dict, ...), c'est facile.

    Exemple de conversion d'un dictionnaire en texte:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    D = {'a':[12,5.654, ('x', 'y')], 'b':'azerty'}
    # conversion en texte
    Dt = "%r" % D  # on pourrait aussi utiliser repr(D)
     
    print Dt
    {'a': [12, 5.654, ('x', 'y')], 'b': 'azerty'}
    print type(Dt)
    <type 'str'>
    On voit que le dictionnaire a bien été converti en texte avec son contenu, et qu'on peut donc le mettre "en clair" comme valeur d'une clé dans un fichier .ini (configparser)

    Retour du texte en objet Python:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # conversion du texte en objet Python
    D2 = eval(Dt)
     
    print D2
    {'a': [12, 5.654, ('x', 'y')], 'b': 'azerty'}
    print type(D2)
    <type 'dict'>
    print D2['a'], type(D2['a'])
    [12, 5.654, ('x', 'y')] <type 'list'>
    print D2['a'][2], type(D2['a'][2])
    ('x', 'y') <type 'tuple'>
    On constate que le dictionnaire a été reconstitué dans son bon type, ainsi que ses valeurs imbriquées.

    L'avantage de cette technique est qu'on peut intervenir avec un traitement de texte pour lire ou modifier les objets directement dans le fichier .ini.

    L'inconvénient est qu'on crée un trou de sécurité à cause d'eval: il suffirait de modifier le fichier .ini pour faire avaler des instructions suspectes au programme. On peut limiter cela en testant le contenu du texte avant l'application d'eval.

    Bien entendu, ce n'est valable que pour les objets qui supportent la représentation en texte avec repr, et qui peuvent être évaluées avec eval (expression). Pour des cas plus complexes, il vaut mieux rester à des solutions classiques de sérialisation (pickle, shelve, ...). Pour ma part, j'aime bien shelve: http://python.jpvweb.com/mesrecettes...e_recup_objets

    En ce qui concerne le stockage d'objets binaires comme par exemple une image, en tant que texte dans un fichier .ini, c'est tout à fait possible avec le module base64. Exemple ici http://python.jpvweb.com/mesrecettes...ersions_base64.
    Un expert est une personne qui a fait toutes les erreurs qui peuvent être faites, dans un domaine étroit... (Niels Bohr)
    Mes recettes python: http://www.jpvweb.com

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2011
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 15
    Points : 8
    Points
    8
    Par défaut
    Citation Envoyé par tyrtamos Voir le message
    Bonjour,
    Bien entendu, ce n'est valable que pour les objets qui supportent la représentation en texte avec repr, et qui peuvent être évaluées avec eval (expression). Pour des cas plus complexes, il vaut mieux rester à des solutions classiques de sérialisation (pickle, shelve, ...). Pour ma part, j'aime bien shelve: http://python.jpvweb.com/mesrecettes...e_recup_objets
    Merci de ta réponse,
    Donc, pour chaque classe, faut-il que j'écrive une méthode de sérialisation dans le cas d'objets complexes ?

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Citation Envoyé par silvio7 Voir le message
    ça pourrait ressembler à de la serialization effectivement. Mais il me manque quelques exemples concrets
    Sinon il me semblait que Pickle n'enregistrait qu'en binaire...
    pickle sérialise: il transforme en "texte".
    Soucis, il n'est pas "construit" pour être modifiable par un humain avec son éditeur favori - enfin on fait ce qu'on veut, mais c'est "sportif".

    Tel que formulé, vous semblez souhaiter stocker l'état d'objets Python dans des fichiers "éditables" et faire l'économie d'une analyse du contenu de ces fichiers pour mettre à jour les objets Python correspondants.

    Avec une liste de dictionnaire keys, values vous pouvez utilisez ce que vous voulez: CSV, JSON, ConfigParser,...
    Le plus compact sera sans doute .CSV: le header vous donne le nom des attributs et les rows/lignes la valeur des champs pour chaque objet

    Dans la documentation du module collections, vous trouvez en illustration de named tuple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    from collections import namedtuple
    EmployeeRecord = namedtuple('EmployeeRecord', 'name, age, title, department, paygrade')
     
    import csv
    for emp in map(EmployeeRecord._make, csv.reader(open("employees.csv", "rb"))):
        print(emp.name, emp.title)
     
    import sqlite3
    conn = sqlite3.connect('/companydata')
    cursor = conn.cursor()
    cursor.execute('SELECT name, age, title, department, paygrade FROM employees')
    for emp in map(EmployeeRecord._make, cursor.fetchall()):
        print(emp.name, emp.title)
    note: on peut s'inspirer d'une illustration, même si ce n'est pas ce que vous voulez...

    Lorsque les objets ont des liens entre eux... la complexité est autre: si employee contient manager "pointeur" vers un employé particulier, que pourra-t-on mettre dans la forme sérialisée?
    1. le "repr" du manager?
    2. l'identifiant du manager?


    Dans le premier cas, les mises à jour de la version sérialisée de manager devront être propagée sur les différents employés qu'il manage...

    L'identifiant permet de se passer d'avoir à propager mais nous sortons un peu de la sérialisation d"objets" pour aller dans le mapping entre des entités externes et leur représentation "interne".

    En mode sérialisé "pur", XML offre tout ce qu'il faut pour supporter cela mais ce n'est pas des plus simple à utiliser. Les ORM tels que SQLAlchemy ou Elixir apportent des solutions mais il faut prendre le temps d'apprendre.

    Dit autrement:
    - clés/valeurs: pas de problème.
    - relations: XML ou ORM si "compliqué".

    La plupart du temps on est entre les deux... les relations ne sont pas suffisamment compliquées pour opter vers un ORM/XML. Et on ne sait pas trop apprécier le niveau de complexité qui mériterait...

    note: vous avez probablement besoin d'un ORM si on ne peut réduire les relations:
    - à une hiérarchie simple (père, fils), ou
    - a des "liens" entre objets appartenant à des hiérarchies simples.
    note: ce qui ferme un peu le type de relations possibles entre objets.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2011
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 15
    Points : 8
    Points
    8
    Par défaut
    Bonsoir,

    et merci pour votre réponse,

    Citation Envoyé par wiztricks Voir le message
    Salut,
    Tel que formulé, vous semblez souhaiter stocker l'état d'objets Python dans des fichiers "éditables" et faire l'économie d'une analyse du contenu de ces fichiers pour mettre à jour les objets Python correspondants.
    Que voulez-vous voulez dire par "économie d'une analyse du contenu" ?


    Avec une liste de dictionnaire keys, values vous pouvez utilisez ce que vous voulez: CSV, JSON, ConfigParser,...
    Le plus compact sera sans doute .CSV: le header vous donne le nom des attributs et les rows/lignes la valeur des champs pour chaque objet

    Lorsque les objets ont des liens entre eux... la complexité est autre: si employee contient manager "pointeur" vers un employé particulier, que pourra-t-on mettre dans la forme sérialisée?
    1. le "repr" du manager?
    2. l'identifiant du manager?


    Dans le premier cas, les mises à jour de la version sérialisée de manager devront être propagée sur les différents employés qu'il manage...

    L'identifiant permet de se passer d'avoir à propager mais nous sortons un peu de la sérialisation d"objets" pour aller dans le mapping entre des entités externes et leur représentation "interne".
    Celà ressemble effectivement au cas que je décris.

    En mode sérialisé "pur", XML offre tout ce qu'il faut pour supporter cela mais ce n'est pas des plus simple à utiliser. Les ORM tels que SQLAlchemy ou Elixir apportent des solutions mais il faut prendre le temps d'apprendre.

    Dit autrement:
    - clés/valeurs: pas de problème.
    - relations: XML ou ORM si "compliqué".

    La plupart du temps on est entre les deux... les relations ne sont pas suffisamment compliquées pour opter vers un ORM/XML. Et on ne sait pas trop apprécier le niveau de complexité qui mériterait...

    note: vous avez probablement besoin d'un ORM si on ne peut réduire les relations:
    - à une hiérarchie simple (père, fils), ou
    - a des "liens" entre objets appartenant à des hiérarchies simples.
    note: ce qui ferme un peu le type de relations possibles entre objets.

    - W
    Je ne sais pas si mon cas est "compliqué". Mais dans tous les cas, je cherche une solution plutôt simple et rapide.

    j'ai un objet du type:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class objet1
     
        def __init__(self)
               self.liste1=[] # liste d'obj2
               self.i=1
     
    class objet2
     
        def __init__(self,i)
               self.nom="nomobjet2"
               self.i=i
    Pour chaque classe, je dois donc écrire la méthode de sérialisation correspondante et de "dé"-sérialization, c'est bien ça?

    merci pour vos précisions.

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Salut,

    Que voulez-vous voulez dire par "économie d'une analyse du contenu" ?
    Une couche pour effectuer le "serdes" entre les objets et la persistance qui soit "plus épaisse" que __str__ et eval.

    Je ne sais pas si mon cas est "compliqué". Mais dans tous les cas, je cherche une solution plutôt simple et rapide.
    Ce sont vos exigences qui rendent la réalisation "compliquée":
    - oubliez la possibilité de mettre à jour l'état des objets avec un éditeur et vous pourriez utiliser pickle (*)
    - limitez les objets à des dictionnaires de clés/valeurs et JSON ferait l'affaire.

    (*) pickle sait sauver et restaurer les références que peuvent avoir les objets entre eux... pourvu qu'on les traite en même temps, genre restauration au démarrage, sauvegarde à la sortie. Au delà c'est moins simple...

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2011
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 15
    Points : 8
    Points
    8
    Par défaut
    Bonjour,

    Je reviens sur ce sujet après quelques semaines de réflexions, et développements.
    J'ai donc opté pour l'utilisation d'un objet ConfigParser, afin d'obtenir un fichier du style Section, Clé=Valeur.
    J'ai donc une classe qui va lire le fichier, et créer les objets. Chaque objet devant être "configuré" suivant les clés qui lui sont propres. Un objet pouvant être représenté par une section complète, avec à chaque fois cléX=valeurY, ou bien, directement par une clé : CléObjetX=valeur1,valeur2,valeur3.

    Seulement j'aimerais décorreller le plus possible les aspects lecture/écriture de conf, des aspects logique du programme.

    Faut-il définir les classes comme ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class obj1:
     
      def methode1():
        ....
     
      def  lireconfig():
        ....
     
      def sauverconfig():
         ....
    ou plutôt:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class obj1(config_obj1):
     
      def methode1():
        ....
     
    class config_obj1(maconfig):
     
      def  lireconfig():
        ....
     
      def sauverconfig()
         ....
    ou autre?

    Ma question est donc plus d'ordre "architecture" ou pattern.

    merci d'avance,
    Silvio

  10. #10
    Membre expérimenté
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    946
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 946
    Points : 1 351
    Points
    1 351
    Par défaut
    Salut,

    Je pense que rajouter les méthodes lireconfig() et sauverconfig() complique énormément la tâche et du coup augmente la possibilité de bugs, car pour chaque classe dont tu veux sauver une instance, il faut prévoir et coder ces deux méthodes qui ne sont pas à priori factorisables. Je crois que c'est ce voulait dire wiztricks avec "économie d'une analyse du contenu".

    Parlons un peu de maintenance, pour chaque ajout ou retrait d'une propriété dans une classe, il faut modifier aussi ces deux méthodes. Alors que le module pickle est fait pour ça.

    je connais bien le module ConfigParser, je l'utilise souvent, mais uniquement pour sauver des configurations d'applications. Dans ce contexte, il est excellent. Je n'essaierais pas de coder des sauvegardes d'objets avec. Les types utilisés sont très simples, booléens, entiers, flottants et chaines. Pas de listes ni de dictionnaires, si tu as dans tes classes quelque chose du genre à coder, je te prédis une belle usine à gaz. Pour une simple liste
    maliste = ['azerty', 123, 1.3, True]
    tu devrais générer un fichier du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    [maliste]
    element_0 = azerty
    element_1 = 123
    element_2 = 1.3
    element_3 = True
    Quand tu voudras récupérer maliste, il faudra que tu saches que maliste est une liste, et que element_1 est un entier, element_2 un flottant, sinon, ils seront interprété comme une chaine. De plus ConfigParser ne respecte pas l'ordre des clefs, il faudra retrouver l'ordre en analysant l'entier concaténé a chaque clef (le 0 de element_0, le 1 de element_1, etc...).

    Je suis d'accord que rien n'est impossible et je ne connais pas les classes que tu veux créer, j'attire simplement ton attention sur ces futures difficultés...

    A+

    Pfeuh

  11. #11
    Futur Membre du Club
    Profil pro
    Inscrit en
    Juin 2011
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 15
    Points : 8
    Points
    8
    Par défaut
    salut,
    merci de ta réponse,

    Problème, c'est que Pickle ne génère pas un fichier texte. D'autant plus que quelque chose de généré automatiquement n'est pas "facilement" éditable.

    Donc dans l'optique de ce que je souhaite faire, il me semble qu'il n'y a donc pas de solution "simple" pour sauvegarder et lire des instances de classe "proprement" et de façon lisible. Mais ça reste quand même l'idée de sauvegarde de "configuration" de programme.

  12. #12
    Membre éprouvé

    Homme Profil pro
    Diverses et multiples
    Inscrit en
    Mai 2008
    Messages
    662
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Diverses et multiples

    Informations forums :
    Inscription : Mai 2008
    Messages : 662
    Points : 1 273
    Points
    1 273
    Par défaut
    Une solution intermédiaire pourrait être que chaque classe dispose d’une méthode pour générer un dict (de valeurs “simples”), et d’une autre pour se “reconstruire” à partir de ce dict.

    Ensuite, tu n’as plus qu’à enregistrer (ou lire) ce dict dans le format que tu veux (config, ou, plus puissant, JSON, par ex.).

Discussions similaires

  1. Meilleure façon de sauvegarder un objet dans un fichier ?
    Par piotrr dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 29/10/2008, 11h40
  2. Réponses: 14
    Dernier message: 24/07/2006, 12h09
  3. Les fichiers de configuration de comptes avec Samba
    Par tomnie dans le forum Réseau
    Réponses: 4
    Dernier message: 18/03/2004, 08h30
  4. [arbre] Sauvegarder un objet dans un fichier
    Par Guigui_ dans le forum Langage
    Réponses: 6
    Dernier message: 07/02/2003, 00h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo