Partage
  • Partager sur Facebook
  • Partager sur Twitter

Ecrire dans un fichier externe

Sujet résolu
    16 novembre 2017 à 17:18:52

    Bonjour à tous,

    J'aimerais écrire sur des fichiers externes (ajouter, pas écraser) mais je n'y arrive pas et je vois pas trop d'où vient l'erreur. J'utilise python/flask sous linux.

    En gros ça c'est mes dossiers : '/home/nsaidana/DEV/DHCP.final/app/static/DATA/'

    Mon "view.py"  est dans "app" et mes fichiers dans "DATA" (voir le chemin plus haut).

    Voilà mon code (j'ai aucune erreur mais mon code ne fait rien) :

    @app.route('/filechange', methods=['GET','POST'])
    def add_entry():
    
        dir_name = '/home/nsaidana/DEV/DHCP.final/app/static/DATA/'
    
        if request.method == 'POST':
            file_name = request.form['file_name']
            files_table = []
            for root, dirs, files in os.walk(dir_name):
                for f in files:
                    if f == file_name:
    
                        entry = {
                            "host" : request.form['host_name'],
                            "mac"  : request.form['mac_address'],
                            "ip"   : request.form['ip_address']
                        }
    
                        with open('file_name', 'a') as file:
    
                            my_pickler = pickle.Pickler(file)
                            my_pickler.dump(entry)
                    
                    return render_template('files_list.html')
    
        return render_template('file_change.html')


    Merci d'avance.

    • Partager sur Facebook
    • Partager sur Twitter
      16 novembre 2017 à 22:40:56

      Salut,

      Je ne crois pas que l'on peut ajouter des données. Surtout si vous avez un dictionnaire, sans clef unique. 

      Exemple:

      import pickle
      
      FILE = 'testing.pkl'
      
      entry = {
          'host': 'salut',
          'ip': '192.168.1.1',
      }
      entry2 = {
          'host': 'allo',
          'ip': '192.168.1.8',
      }
      
      def write(file, data, mode='ab'):
          with open(file, mode) as f:
              ## CHOIX 1:
              #my_pickler = pickle.Pickler(f)
              #my_pickler.dump(data)
              ## CHOIX 2:
              pickle.dump(data, f)
      
      def read(file):
          with open(file, 'rb') as f:
              data = pickle.load(f)
          return data
      
      ## Première
      write(FILE, entry)
      print(read(FILE))
      
      ## Deuxième
      write(FILE, entry2)
      print(read(FILE))

      Vous sauvegardez un dictionnaire. Il manque la clef (id) unique. Sinon, on modifie le dictionnaire (on ajoute pas).

      entry = {
          '0': {'host': '', 'ip': ''},
          '1': {'host': '', 'ip': ''},
      }
      

      Au pire, vous devriez mettre vos dictionnaires dans une liste, ainsi, les index seront l'id unique.

      Pour finir, le mieux serait de prendre tous les données et ajouter vous-même les nouvelles informations.

      Ensuite, vous sauvegardez.

      def write(file, data, mode='wb'):
          with open(file, mode) as f:
              pickle.dump(data, f)
      
      def read(file):
          with open(file, 'rb') as f:
              data = pickle.load(f)
          return data
      
      def appending(file, new_data):
          data = read(file) ## Lire les anciens
          data.extend(new_data) ## Ajoutes les nouvelles aux anciennes
          write(file, data) ## Écrit la nouvelle liste
      
      
      write(FILE, [entry]) ## Met dans une liste
      print(read(FILE))
      
      appending(FILE, [entry2]) ## Met dans une liste
      print(read(FILE))



      J'espère qu c'est ce que vous demandiez :)

      N'hésitez pas pour les questions.

      Bonne chance

      A+

      • Partager sur Facebook
      • Partager sur Twitter
        17 novembre 2017 à 12:02:30

        Tout d'abord merci beaucoup pour les explications, mais je dois t'avouer qu'il y a encore pleins de trucs que je n'ai pas très bien saisis.

        FILE = 'testing.pkl'

        Je suppose que ça c'est pour créer un nouveau fichier? sinon pourquoi pas .txt? j'ai jamais vu de fichier .pkl lol

        Par curiosité, pourquoi tu définis la fonction "write" avant "read"? (sachant que t'obtient "data" grâce à "read()")

        Ton premier programme me renvoie deux fois la même chose (peut-être c'est moi qui l'ai mal écris, si c'est le cas tu peux ignorer cette partie) :

        {'ip': '192.168.1.1', 'host': 'salut'}
        {'ip': '192.168.1.1', 'host': 'salut'}

        Après j'ai pas compris cette ligne, tu charges un objet de "f", mais les objets qu'on est censé utiliser c'est pas les dictionnaires "entry" ?

        data = pickle.load(f)


        -Je sais que "b" fait référence à "binaire", mais quand on l'utilise on ne comprends plus ce qu'il y a dans notre fichier(illisible), du coup on doit exécuter le programme pour voir/comprendre ce qu'on a à chaque fois?

        -Pour les modes je ne sais pas si utiliser "w" va m'être utile, j'ai des fichiers qui contiennent déjà des dictionnaires et  je veux en rajouter plus, où est-ce qu'il vaut mieux prendre ta méthode "appending()" que "write()" dans mon cas?

        -J'ai pas très bien compris l'histoire des "id", j'ai cru qu'on utilisais des "id" seulement quand on travaillait avec des bases de données, là t'utilise "extend()" et ton "entry2" n'a pas d'id donc je ne vois pas trop l'utilité.

        -Pourquoi les "entry" sont entre crochets à la fin? c'est quand que tu spécifie que tu travaille avec des listes? "c'est pickle.load()" qui renvoie une liste?

        -Pour conclure, il n'y a vraiment pas moyen de localiser des fichiers dans un autre dossier? là tes données sont dans le même fichier qui contient tes programmes, mais si on veut les séparer (comme dans mon cas) comment on peut y accéder?

        Sinon mes fichiers contiennent quelques dictionnaires du type :

        host host_name.fr {
        	hardware ethernet 15:16:75:63:dd:dc;
        	fixed-address 17.5.2.175;
        }
        
        host another_host_name.fr {
        	hardware ethernet 18:16:75:63:dd:dc;
        	fixed-address 27.5.8.175;
        }

        Désoler si j'ai posé énormément de questions, je suis encore nouveau avec python T_T


        • Partager sur Facebook
        • Partager sur Twitter
        Anonyme
          17 novembre 2017 à 17:58:37

          pickle lit et écrit uniquement du binaire.

          Tes fichiers ne contiennent visiblement pas des dictionnaires.

          Il faut être plus attentif à ce que tu fais, par exemple dans ton poste original, tu nomme une variable file_name et après tu passe en argument à open la chaîne "file_name" au lieu de la variable...

          -
          Edité par Anonyme 17 novembre 2017 à 18:01:26

          • Partager sur Facebook
          • Partager sur Twitter
            17 novembre 2017 à 23:07:54

            Bonsoir ,

            Pour séparer les fichiers "programme" et les fichiers "données", il est possible d'utiliser le module os.

            import os # importation du module
            
            os.chdir(os.path.expanduser('~/dossier_stockage/'))# permet de se placer dans le dossier choisi, ici dossier_stockage

            Il suffit d'importer le module au début du code, et de se placer dans le dossier choisi avant chaque ouverture/enregistrement de données.

            Pour info le signe ~ désigne le répertoire racine.

            • Partager sur Facebook
            • Partager sur Twitter
              21 novembre 2017 à 22:10:44

              Salut,

              Désolé, pour l'attente.

              Avant de commencer, les extensions de fichier n'ont aucun rapport.

              On nomme les fichiers pickles avec .pkl uniquement pour savoir, que c'est un fichier binaire (pickle). Vous pouvez le nommer .txt, mais ce n'est pas parce que votre fichier à une extension .txt, que vous pouvez le lire directement en cliquant dessus.

              Il en va de même, avec les fichier json. Que l'on nomme .jsn (C'est uniquement pour les reconnaître)

              De plus, je crois que la principale raison est: Windows détecte les fichier .txt, comme étant du texte, mais cela ne veux rien dire. Vous risquer d'avoir des erreurs, surtout s'il essaye de le lire.

              Premièrement, effectivement, le module pickle est pour le binaire. Vous pourrez jamais voir ce qu'il contient, simplement en cliquant dessus.

              Si vous voulez avoir accès au fichier en tout temps, vous devriez utiliser le module json.

              Deuxièmement, pour les modes, il y a seulement les fichiers normaux, qui peuvent ajouter.

              Avec pickle et json, vous devez charger le fichier au complet, et ensuite vous apportez les modifications. Pour finir, vous sauvegarder le nouveau par dessus l'ancien. (On peut pas ajouter)

              C'est ce que mon premier exemple tente de vous démontrez. (Il n'y a pas d'erreur, il affiche bien deux fois la même chose). Puisqu'on ne peut pas ajouter. (L'exemple servait justement à démontrer que l'on ne peut pas ajouter)

              Troisièmement, oui les objets qui seront chargés par pickle.load(f), sera TOUT la variable que vous avez sauvegardé (donc, le dictionnaire)

              Exemple, pour l'écriture:

              import pickle
              
              mon_fichier = 'testing.pkl'
              
              mon_dico = {
                  'salut': 1234,
                  'coucou': 5678,
              }
              
              ## Écriture (Sauvegarde tout le dictionnaire, en binaire)
              with open(mon_fichier, 'wb') as f:
                  pickle.dump(mon_dico, f)
              

              Exemple, pour la lecture:

              import pickle
              
              mon_fichier = 'testing.pkl'
              
              ## Lecture (Chargement du fichier)
              with open(mon_fichier, 'rb') as f:
                  mon_dico = pickle.load(f)
              
              print(mon_dico)

              Comme vous le voyez, j'ai rennomé le data = pickle.load(f) (de l'exemple précédent) par mon_dico, pour que vous voyez que c'est uniquement une variable.

              Quatrièmement, concernant les 'id', ce que je voulais dire (oui, c'est mélangeant), c'est que pour  ajouter des éléments (clef, valeur) dans un dictionnaire, on doit avoir une clef unique. Sinon, on modifie l'ancienne, on n'ajoute pas.

              entry = {
                  'host': 'allo',
                  'ip': '192.168.1.1',
              }
              ## ON MODIFIE, on ajoute pas...
              entry['host'] = 'salut'
              
              print(entry)
              

              Si je change host, je change la valeur de host. J'ajoute pas un nouveau host, puisque la clef 'host' existe déjà, donc je modifie l'ancienne.

              Honnêtement, je ne connais pas tous les bons mots, pour expliquer tout la théorie. Mais c'est la base de python.

              Exemple de clef unique:

              entry = {
                  'bob': {'host': 'salut', 'ip': '192.168.1.1'},
                  'pierre': {'host': 'allo', 'ip': '192.168.1.2'},
              }

              OU bien, si vous avez pas de clef unique, comme j'ai écrit suffit de mettre votre dictionnaire dans une liste. Le 'id' sera l'index dans la liste. (à la place de 'bob' et de 'pierre')


              Cinquièmement, si vous sauvegardez un dictionnaire dans pickle, il vous retournera un dictionnaire lors du chargement. Si vous écrivez une liste, il vous retournera une liste. (En résumé, il vous retourne ce que vous avez sauvegardé TEL QUEL, mot pour mot, ligne par ligne...).

              Pour tous les autres questions, je vais attendre, d'un coup que j'ai répondu :)

              N'hésitez pas pour les questions. Je vous ai peut-être mélangé, en donnant des exemples, qui démontrait que cela est impossible d'ajouter en passant par un dictionnaire uniquement.

              Bonne chance

              A+

              • Partager sur Facebook
              • Partager sur Twitter
                22 novembre 2017 à 11:01:38

                En faite c'est moi qui a compliqué les choses, je débute en python et je n'ai pas réussi à faire un bon programme qui faisait ce que je voulais, j'ai vu qu'on pouvait faire des choses intéressantes avec "pickle" mais je ne le maîtrise pas non plus et les fichiers en binaires ne me sont d'aucune utilités...

                @IdiotBête C'est vrai j'avais pas fait attention, merci.

                @pastille Le truc que je comprends pas c'est que si je définis mes données dans le fichier racine ils ne vont pas être disponible dans le dossier/repository de mon projet du coup en quoi ça me sert?

                @nolimitech Franchement je ne sais pas quoi te dire, un ENORME merci pour toutes tes explications, j'ai appris pas mal de choses, de plus je peux voir que tu n'es pas vraiment français du coup j'apprécie ton aide ENCORE plus, encore merci.

                On m'as finalement aidé à faire ce que je voulais (ou presque), je met le code juste en dessous au cas où :

                Pour lire les fichiers ".txt" et renvoyer une liste de dictionnaires :

                @app.route('/<filename>')
                def list_display(filename):
                    global items
                    pp = pprint.PrettyPrinter(indent=4)
                
                    #filedesc = open("app/static/DATA/fixed.10.3", "r")
                    filedesc = open("app/static/DATA/{}".format(filename), "r")
                    """
                    items2 = []
                    for lines in filedesc:
                        items2 += [lines]
                        print(items2)
                    """
                
                    SCAN = {
                        'host': r"^host (\S+) {",
                        'comment' : r"^#(.*)",
                        'hardware': r"hardware ethernet (\S+);",
                        'fixed_address': r"fixed-address (\S+);",
                        'end_item': r"^\s*}$\s*",
                   }
                
                    # Compile only once, if not want re.compile above
                    #pp.pprint(SCAN.items())
                    for key, expr in SCAN.items():
                        SCAN[key] = re.compile(expr)
                
                    # items = []
                    item = {}
                    for line in filedesc:
                        for key, expr in SCAN.items():
                            #m = expr.search(line)
                            m = re.search(expr, line)
                            if not m:
                                continue
                            if key == 'end_item':
                                items.append(item)
                                #print ([item.get(x) for x in ['host', 'hardware', 'fixed_address']])
                                item = {}
                            else:
                                item[key] = m.group(1)
                
                    pprint.pprint(items)
                
                    return render_template('index.html', filename=filename, items=items)
                


                Et la pour ajouter (je sais que c'est pas l'idéal, mais faut déjà que j'arrive à faire un truc simple) :

                @app.route('/filechange', methods=['GET','POST'])
                def add_entry():
                    global items
                    if request.method == 'POST':
                        #filedesc = open("app/static/DATA/{}".format(request.form['host_name']), "r")
                        items = items + [ { 'fixed_address': request.form['mac_address'],
                            'hardware': request.form['ip_address'],
                            'host': request.form['host_name']}
                            ]
                        #print(items)
                        return render_template("files_list.html", items=items)
                
                    return render_template("file_change.html",items=items)
                


                Le problème c'est que je rends la variable "items" global et travailler avec, mais bon je ferais un autre topic pour ça je pense.

                Je met en résolu, merci pour tout vos aides !

                • Partager sur Facebook
                • Partager sur Twitter
                  22 novembre 2017 à 20:57:54

                  Salut,

                  Effectivement, je suis Canadien-Français (Québec). C'est pour cela que je ne comprends pas toujours ce que vous dites. Cela doit être pareil pour vous. :-°:p:ange: 

                  Ensuite, merci pour votre patience. Vous avez surement lus plusieurs fois mon post, haha. :honte:

                  Pour ce qui est du global, je crois que vous avez pas le choix (si je dis pas de bêtises). Puisque, les paramètres sont pour flask.

                  Si vous pensez avoir plusieurs variables globales, vous avez qu'à créer un dictionnaire, qui sera la seule variable global. (Déjà mieux que 10 variables globales :) )

                  Bonne chance et bonne continuation.

                  A+

                  • Partager sur Facebook
                  • Partager sur Twitter
                    23 novembre 2017 à 9:55:52

                    Je vais d'abord si je peux régler le problème tout seul sinon je posterais un nouveau topic, merci pour l'info !
                    • Partager sur Facebook
                    • Partager sur Twitter

                    Ecrire dans un fichier externe

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown