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 :

Parcourir un fichier créé par cPickle


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut Parcourir un fichier créé par cPickle
    Bonjour,
    le code ci-dessous utilise cPickle pour stocker des variables. Pour le parcours ligne par ligne j'utilise une méthode du type TRY:... EXCEPT:... avec une boucle "infinie".

    Est-il possible de faire autrement, voire plus propre, sachant que je ne peux pas stocker toutes les infos dans un seul objet Python ?

    Par exemple, dans le code ci-dessous, je ne veux pas stocker directement la liste titles.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    #!/usr/bin/env python
    #coding=utf-8
     
    import cPickle
     
    titles = ['Title ' + str(i) for i in range(1,11)]
     
    file = open("test.txt", 'w')
     
    for oneTitle in titles:
        cPickle.dump(oneTitle, file)
    file.close()
     
     
    file = open("test.txt", 'r')
    while True:
        try:
            oneVar = cPickle.load(file)
            print oneVar
        except:
            pass
    file.close()

  2. #2
    Membre émérite

    Profil pro
    Inscrit en
    Août 2004
    Messages
    723
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 723
    Par défaut
    Ta restriction sur le fait de ne pas stocker la liste m'étonne, mais bon, soit.

    Je ne vois pas trop comment faire mieux, à moins de parcourir le fichier une première fois pour isoler les différentes entrées, mais ça revient à faire le boulot de pickle.

    Sinon, je suppose que c'est un break et non un pass dans la clause except...

  3. #3
    Membre Expert
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Par défaut
    Comprends pas.
    Tu vois qu’il y a une boucle infinie, et ça ne te fait rien ?
    Ou bien est-ce cela que tu veux corriger ?
    Pour corriger il sufit de mettre break au lieu de pass



    D’autre part, qu’est ce que tu entends par “stocker“ ?

    Ta ligne titles = ['Title ' + str(i) for i in range(1,11)] crée un objet qui est bien ’stocké’ dans la mémoire , d’une certaine manière. Comment faut-il comprendre ’stocker’ ?

    Si tu veux obtenir des valeurs de ta liste titles mais sans avoir à créer une liste et la “stocker“ en mémoire, c’est un générateur qu’il te faut.
    Cela consiste à remplacer les crochets [ ] de la définition de titres par des parenthèses ( )


    Et si les utilisations des valeurs de titles ne peuvent pas être mises dans une boucle, c’est une fonction génératrice (avec yield) qu’il te faut.



    Et bien sûr, mettre xrange(1,11) au lieu de range(1,11)



    En outre, avec with statement , c’est plus clean, comme tu le demandes.





    J’ai comparé pickle et cPickle avec le code suivant (sans les print pour ne comptabiliser que les opérations de dump et load)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    #!/usr/bin/env python
    #coding=utf-8
     
    from time import clock
    import pickle,cPickle
     
    print 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
     
    te = clock()
    with open("test.txt", 'w') as f:
        for oneTitle in ('Title ' + str(i) for i in xrange(1,11)):
            pickle.dump(oneTitle, f)
    tf = clock()
    a = tf-te
     
    te = clock()
    with open("test.txt", 'r') as f:
        while True:
            try:
                oneVar = pickle.load(f)
                #print oneVar
            except:
                break
    tf = clock()
    b = tf-te
     
    print 'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB'
     
    te = clock()
    with open("testu.txt", 'w') as f: 
        for oneTitle in ('Title ' + str(i) for i in xrange(1,11)):
            cPickle.dump(oneTitle, f)
    tf = clock()
    c = tf-te
     
    te = clock()
    with open("testu.txt", 'r') as f:
        while True:
            try:
                oneVar = cPickle.load(f)
                #print oneVar
            except:
                break
    tf = clock()
    d = tf-te
     
     
    print '\n',a,'   ',b
    print c,'   ',d
    print c/a*100,'      ',d/b*100
    L’écriture avec cPickle prend environ 70 % du temps que met l'écriture avec pickle.

    La lecture avec cPickle prend environ 20 % du temps que met la lecture avec pickle.

  4. #4
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    La boucle serait plus optimisée ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    try:
        while 1:
            # lire des objets
    except:
        pass
    De cette manière, on fait le try/catch une seule fois, plutôt qu'à chaque itération. Aussi, Python optimise le while 1: il ne teste pas la valeur avant chaque tour de boucle, il continue sans rien tester.

    La preuve par le désassemblage
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    >>> def test1():
    ...     while True:
    ...         print "Hello"
    ... 
    >>> def test2():
    ...     while 1:
    ...         print "Hello"
    ...
     
    >>> dis(test1)
      2           0 SETUP_LOOP              17 (to 20)
            >>    3 LOAD_GLOBAL              0 (True)
                  6 JUMP_IF_FALSE            9 (to 18)
                  9 POP_TOP
     
      3          10 LOAD_CONST               1 ('Hello')
                 13 PRINT_ITEM
                 14 PRINT_NEWLINE
                 15 JUMP_ABSOLUTE            3
            >>   18 POP_TOP
                 19 POP_BLOCK
            >>   20 LOAD_CONST               0 (None)
                 23 RETURN_VALUE
     
    >>> dis(test2)
      2           0 SETUP_LOOP               8 (to 11)
     
      3     >>    3 LOAD_CONST               1 ('Hello')
                  6 PRINT_ITEM
                  7 PRINT_NEWLINE
                  8 JUMP_ABSOLUTE            3
            >>   11 LOAD_CONST               0 (None)
                 14 RETURN_VALUE
     
    >>> def test3():
    ...     while 1:
    ...         try:
    ...             print "Hello"
    ...         except:
    ...             pass
    ... 
    >>> def test4():
    ...     try:
    ...         while 1:
    ...             print "Hello"
    ...     except:
    ...         pass
    ...
    >>> dis(test3)
      2           0 SETUP_LOOP              22 (to 25)
     
      3     >>    3 SETUP_EXCEPT             9 (to 15)
     
      4           6 LOAD_CONST               1 ('Hello')
                  9 PRINT_ITEM
                 10 PRINT_NEWLINE
                 11 POP_BLOCK
                 12 JUMP_ABSOLUTE            3
     
      5     >>   15 POP_TOP
                 16 POP_TOP
                 17 POP_TOP
     
      6          18 JUMP_ABSOLUTE            3
                 21 END_FINALLY
                 22 JUMP_ABSOLUTE            3
            >>   25 LOAD_CONST               0 (None)
                 28 RETURN_VALUE
     
    >>> dis(test4)
      2           0 SETUP_EXCEPT            15 (to 18)
     
      3           3 SETUP_LOOP               8 (to 14)
     
      4     >>    6 LOAD_CONST               1 ('Hello')
                  9 PRINT_ITEM
                 10 PRINT_NEWLINE
                 11 JUMP_ABSOLUTE            6
            >>   14 POP_BLOCK
                 15 JUMP_FORWARD             7 (to 25)
     
      5     >>   18 POP_TOP
                 19 POP_TOP
                 20 POP_TOP
     
      6          21 JUMP_FORWARD             1 (to 25)
                 24 END_FINALLY
            >>   25 LOAD_CONST               0 (None)
                 28 RETURN_VALUE
    >>>
    Si la différence est évidente entre les deux premiers exemples, elle l'est moins entre les deux exemples de try/catch.
    En analysant de plus près, on voit que test3 effectue le setup du try/catch à chaque passage dans la boucle. test4 quant à lui ne le fait qu'une fois.
    Bien sur, les deux constructions ne sont pas toujours interchangeables. Mais dans le cas de rambc, elles le sont.


    Bien entendu, l'optimisation de code est ici quasiment inutile, puisqu'on joue avec des fichiers, et que c'est ça qui ralentit le processus.

  5. #5
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Citation Envoyé par oiffrig Voir le message
    Ta restriction sur le fait de ne pas stocker la liste m'étonne, mais bon, soit.
    J'ai mis ici un exemple simplifié. En fait, j'utilise cPickle pour stocker des infos sur des lignes de texte. Pour éviter des éventuels soucis de mémoire, j'ai choisi de travailler ligne par ligne. Du coup, les infos obtenues sur mes lignes originales sont stockées dans des dicos ligne par ligne. Le fichier produit par cPickle sera ensuite lu pour des mises en forme "directement".

    Citation Envoyé par eyquem Voir le message
    D’autre part, qu’est ce que tu entends par “stocker“ ?

    Ta ligne titles = ['Title ' + str(i) for i in range(1,11)] crée un objet qui est bien ’stocké’ dans la mémoire , d’une certaine manière. Comment faut-il comprendre ’stocker’ ?

    Si tu veux obtenir des valeurs de ta liste titles mais sans avoir à créer une liste et la “stocker“ en mémoire...
    Ne compliquons pas le problème. J'ai ajouté de petites explications ci-dessus.


    Citation Envoyé par eyquem Voir le message
    Comprends pas.
    Tu vois qu’il y a une boucle infinie, et ça ne te fait rien ?
    Ou bien est-ce cela que tu veux corriger ?
    Pour corriger il sufit de mettre break au lieu de pass
    Au temps pour moi... J'ai mal extrait mon code. En fait j'utilise (comme vient de le mettre Antoine) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    try:
        while True:
            oneVar = cPickle.load(file)
            print oneVar
    except:
        pass

    Citation Envoyé par eyquem Voir le message
    En outre, avec with statement , c’est plus clean, comme tu le demandes.
    Tout à fait. J'ai pas encore pris l'habitude d'utiliser tout le temps cette méthode.


    Citation Envoyé par eyquem Voir le message
    J’ai comparé pickle et cPickle avec le code suivant (sans les print pour ne comptabiliser que les opérations de dump et load)

    L’écriture avec cPickle prend environ 70 % du temps que met l'écriture avec pickle.

    La lecture avec cPickle prend environ 20 % du temps que met la lecture avec pickle.
    Je pense que me souci vient de ce qu'on n'utilise pas un fichier binaire. Il faudrait voir ce que cela donne avec un accès binaire.

  6. #6
    Membre émérite
    Avatar de Antoine_935
    Profil pro
    Développeur web/mobile
    Inscrit en
    Juillet 2006
    Messages
    883
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur web/mobile

    Informations forums :
    Inscription : Juillet 2006
    Messages : 883
    Par défaut
    Ut devrais normalement ouvrir le fichier en binaire pour cPickle. Pas certain que ce soit requis, mais c'est plus sûr.
    A propos de binaire, Eyquem, as-tu testé les performances avec les autres "protocoles" de cPickle ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    >>> cPickle.HIGHEST_PROTOCOL
    2
    >>> help(cPickle.dump)
    Help on built-in function dump in module cPickle:
     
    dump(...)
        dump(obj, file, protocol=0) -- Write an object in pickle format to the given
     file.
     
        See the Pickler docstring for the meaning of optional argument proto.
    Et donc
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cPickle.dump(obj, file, cPickle.HIGHEST_PROTOCOL

  7. #7
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Le code suivant montre effectivement la lenteur de pickle relativement à cPickle même après modification du TRY:.. EXCEPT:... :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    #!/usr/bin/env python
    #coding=utf-8
     
    from time import clock
    import pickle,cPickle
     
    print 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
     
    te = clock()
    with open("test.txt", 'w') as f:
        for oneTitle in ('Title ' + str(i) for i in xrange(1,11)):
            pickle.dump(oneTitle, f)
    tf = clock()
    a = tf-te
     
    te = clock()
    with open("test.txt", 'r') as f:
        try:
            while True:
                oneVar = pickle.load(f)
                #print oneVar
        except:
            pass
    tf = clock()
    b = tf-te
     
    print 'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB'
     
    te = clock()
    with open("testu.txt", 'w') as f:
        for oneTitle in ('Title ' + str(i) for i in xrange(1,11000)):
            cPickle.dump(oneTitle, f)
    tf = clock()
    c = tf-te
     
    te = clock()
    with open("testu.txt", 'r') as f:
        try:
            while True:
                oneVar = cPickle.load(f)
                #print oneVar
        except:
            pass
    tf = clock()
    d = tf-te
     
    print 'pickle',
    print '\n\tEcriture : ',a ,'   Lecture : ', b
    print 'cPickle',
    print '\n\tEcriture : ',c ,'   Lecture : ', d
    On obtient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    pickle 
    	Ecriture :  0.0    Lecture :  0.0
    cPickle 
    	Ecriture :  0.04    Lecture :  0.02

  8. #8
    Membre éprouvé

    Profil pro
    Account Manager
    Inscrit en
    Décembre 2006
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Localisation : France, Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Account Manager

    Informations forums :
    Inscription : Décembre 2006
    Messages : 2 301
    Par défaut
    Bien vu Antoine. Quant l'usage de fichier binaire, cela n'y change rien à l'affaire.

    Code pour essayer :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    #!/usr/bin/env python
    #coding=utf-8
     
    from time import clock
    import pickle,cPickle
     
    print 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
     
    te = clock()
    with open("test.txt", 'w') as f:
        for oneTitle in ('Title ' + str(i) for i in xrange(1,11)):
            pickle.dump(oneTitle, f)
    tf = clock()
    a = tf-te
     
    te = clock()
    with open("test.txt", 'r') as f:
        try:
            while True:
                oneVar = pickle.load(f)
                #print oneVar
        except:
            pass
    tf = clock()
    b = tf-te
     
    print 'BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB'
     
    te = clock()
    with open("testu.txt", 'wb') as f:
        for oneTitle in ('Title ' + str(i) for i in xrange(1,11000)):
            cPickle.dump(oneTitle, f, cPickle.HIGHEST_PROTOCOL)
    tf = clock()
    c = tf-te
     
    te = clock()
    with open("testu.txt", 'rb') as f:
        try:
            while True:
                oneVar = cPickle.load(f, cPickle.HIGHEST_PROTOCOL)
                #print oneVar
        except:
            pass
    tf = clock()
    d = tf-te
     
    print 'pickle',
    print '\n\tEcriture : ',a ,'   Lecture : ', b
    print 'cPickle',
    print '\n\tEcriture : ',c ,'   Lecture : ', d
    Ceci étant dit, l'écriture reste "lente" car on obtient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    pickle 
    	Ecriture :  0.0    Lecture :  0.0
    cPickle 
    	Ecriture :  0.03    Lecture :  0.0

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 4
    Dernier message: 17/04/2015, 12h32
  2. Parcourir un dossier et lire les fichier 1 par 1.
    Par jamsgoodon dans le forum Débuter
    Réponses: 15
    Dernier message: 08/02/2011, 11h06
  3. Parcourir un fichier .txt en dos caractère par caractère
    Par berthelot_n dans le forum Scripts/Batch
    Réponses: 1
    Dernier message: 02/07/2009, 10h49
  4. parcourir les fichiers d'un dossier, fichier par fichier
    Par gregcat dans le forum Windows Forms
    Réponses: 9
    Dernier message: 18/04/2008, 15h40
  5. Réponses: 6
    Dernier message: 02/09/2003, 15h12

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