Partage
  • Partager sur Facebook
  • Partager sur Twitter

pickle lire une liste sans la charger en mémoire

    11 août 2015 à 8:52:49

    Bonjour, j'ai une question, j'ai mis une liste dans un fichier avec pickle, peut on lire maliste[0] ou maliste[10] sans charger toute la liste en mémoire ?

    voila c'est tous.

    Le but d'utiliser pickle dans mon cas est d’économiser en mémoire, j'ai une liste qui contient beaucoup de données mais je m'en sert peu dans le programme. L'idée serait donc de la stocker sur le disque dur sans impacter la mémoire.

    • Partager sur Facebook
    • Partager sur Twitter
      11 août 2015 à 9:24:29

      J'ai du mal a comprendre, je n'utilise pas numpy, mais une liste, et pour mmap je vois pas en quoi sa pourrait m'aider ? mmap je peut manipuler les chaîne de caractère, dans mon cas j'ai une liste 2D a traité contenant des données (nombres ou caractère)
      • Partager sur Facebook
      • Partager sur Twitter
        11 août 2015 à 9:36:24

        Si tu utilises des listes trèèèèèès longues et que tu n'utilises pas numpy, je pense que tu n'approches pas le problème de la bonne manière. Tu vas très vite te retrouver avec des problèmes de performances.

        • Partager sur Facebook
        • Partager sur Twitter
          12 août 2015 à 9:00:54

          Mon programme reçoit une liste 2D,k contenant des données (entier ou caractère ou parfois les 2 sont mélangée), ce n'est pas moi qui fait cette liste, mais une machine qui me l'envoie chaque matin dont je ne peut pas modifier le code.

          Je suis obliger d'avoir cette grosse liste.

          Mais j'aimerais m'en "débarrasser", c'est a dire une fois qu'une fois que je l'ai reçu intégralement, je la vide de la mémoire.

          C'est pas non plus une très grosse liste, elle pèse environ 400mo dans la ram, mais je préférerais la stoker dans un fichier, car cette liste au final je fais très peu d’accès en lecture et aucun en écriture.

          J'ai testé pickle, sa marche très bien, mais pour pouvoir lire un élément de cette liste je dois la recharger en mémoire intégralement, pas top comme solution.

          import pickle
          
          a = ['test value','test value 2','test value 3']
          file_Name = "testfile"
          fileObject = open(file_Name,'wb') 
          pickle.dump(a,fileObject)
          fileObject.close()
          
          
          #pour lire
          b = pickle.load(fileObject)
          
          

          y'aurais pas un moyen pour lire uniquement la partie qui m’intéresse ? par exemple a[2]

          -
          Edité par mathema 12 août 2015 à 9:01:17

          • Partager sur Facebook
          • Partager sur Twitter
            12 août 2015 à 10:36:39

            avec pickle tu peut écrire dans le fichier élément par élément, par contre pour la lecture, je ne pense pas.

            Il faudra utiliser autre que pickle je pense.

            -
            Edité par zearte 12 août 2015 à 10:37:01

            • Partager sur Facebook
            • Partager sur Twitter
              12 août 2015 à 13:39:32

              Je te propose cette petite classe. Bien entendu accéder à un élément n'est pas rapide, mais on ne prend qu'un seul élément à la fois en mémoire. Il y a toujours un compromis à trouver entre mémoire utilisée, CPU ou rapidité. Dans notre cas on réduit la taille de la mémoire mais on est plus lent.

              import pickle
              import itertools
              

              class ListOnDisk:

              def __init__(self, filename):
                  self.filename = filename
              
              @staticmethod
              def save(my_list, filename):
                  with open(filename, 'wb') as f:
                      for elt in my_list:
                          pickle.dump(elt, f)
              
              def __iter__(self):
                  with open(self.filename, "rb") as f:
                      while True:
                          try:
                              obj = pickle.load(f)
                          except EOFError:
                              break
                          yield obj
              
              def __getitem__(self, index):
                  it = iter(self)
                  try:
                      return next(itertools.islice(it, index, index+1))
                  except TypeError: # We received maybe a slice object as index
                      return list(itertools.islice(it, index.start, index.stop, index.step))
              

              Notre list

              a = [1, 2, 'hello world!', dict()]

              On la sauvegarde une bonne fois pour toute sur le disk.

              ListOnDisk.save(a, "test-pickle.dat") del a

              On crée une instance de ListOnDisk en donnant le nom du fichier contenant la liste

              list_on_disk = ListOnDisk("test-pickle.dat")

              Et on peut accéder à la liste avec un index ou des slices.

              print(list_on_disk[2]) print(list_on_disk[1:3])

              </pre> L'idée est donc qu'on a pas picklé la liste, mais chacun de ses éléments individuellement. On accède aux éléments avec un générateur, en lisant les éléments un à un jusqu'à trouver le bon.

              -
              Edité par Dan737 12 août 2015 à 13:41:13

              • Partager sur Facebook
              • Partager sur Twitter
                12 août 2015 à 15:31:26

                oui merci, de plus pc qui reçoit la liste a un SSD, ce qui diminue grandement la lenteur.
                • Partager sur Facebook
                • Partager sur Twitter
                  12 août 2015 à 15:46:56

                  J'ai eu un MemoryError a la ligne 12, comme je l'ai signalé, il s'agit d'une liste 2D, (des listes dans une liste), certaine liste sont très grosse, et donc font dépasser le programme(32bits) des 2Go de ram max.

                  J'ai donc optimisé la fonction save comme ceci:

                      def save(my_list, filename):
                          with open(filename, 'wb') as f:
                              for elt in my_list:
                                  pickle.dump(len(elt), f)
                                  for element in elt:
                                      pickle.dump(element, f)

                  Mais je bloque pour la lecture de la liste

                  La lecture se passe bien dans la fonction iter ?

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Anonyme
                    12 août 2015 à 17:02:20

                    Tant que tu ne seras pas plus précis sur ce qu'est cette liste de sous-liste, il sera difficile de t'aider.

                    Pour le moment, je crois que tu n'utilises pas du tout le bon type de données pour manipuler le contenu de ses listes, qui semble plus être un tableau de données (lignes/colonnes)...

                    -
                    Edité par Anonyme 12 août 2015 à 17:02:50

                    • Partager sur Facebook
                    • Partager sur Twitter
                      12 août 2015 à 17:13:21

                      Le problème est que tu linéarises les données. Tu perds donc les informations concernant quel élément appartient à quelle liste. Pour reconstruire ta liste de listes, tu n'as plus aucun moyen de savoir si la première liste à 5, 10 ou 30 éléments.

                      Je me demande si tu ne ferais pas mieux de te diriger vers une base de données alors, genre sqlite3.

                      • Partager sur Facebook
                      • Partager sur Twitter
                        12 août 2015 à 17:45:59

                        passer a une BDD sa me parait un peu trop pour mon besoin quand même.

                        Voici un exemple:

                        import pickle
                        import itertools
                         
                        class ListOnDisk:
                            def __init__(self, filename):
                                self.filename = filename
                         
                            @staticmethod
                            def save(my_list, filename):
                                with open(filename, 'wb') as f:
                                    for elt in my_list:
                                        pickle.dump(elt, f)
                             
                            def __iter__(self):
                                with open(self.filename, "rb") as f:
                                    while True:
                                        try:
                                            obj = pickle.load(f)
                                        except EOFError:
                                            break
                                        yield obj
                         
                            def __getitem__(self, index):
                                it = iter(self)
                                try:
                                    return next(itertools.islice(it, index, index+1))
                                except TypeError: # We received maybe a slice object as index
                                    return list(itertools.islice(it, index.start, index.stop, index.step))
                         
                         
                        # Notre list
                        list1=[0,1,2,3,4]
                        list2=[2,8,7,9,10,14]
                        a = [list1, list2]
                        # On la sauvegarde une bonne fois pour toute sur le disk.
                        ListOnDisk.save(a, "test-pickle.dat")
                        del a
                         
                        # On crée une instance de ListOnDisk en donnant le nom du fichier contenant la liste
                        list_on_disk = ListOnDisk("test-pickle.dat")
                        # Et on peut accéder à la liste avec un index ou des slices.
                        print(list_on_disk[2])
                        print(list_on_disk[1:3])



                        L'idée serait de pickler élément par élément de list1 et list2 et pas d'un seul coup.

                        -
                        Edité par mathema 12 août 2015 à 17:46:53

                        • Partager sur Facebook
                        • Partager sur Twitter

                        pickle lire une liste sans la charger en mémoire

                        × 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