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

  1. #1
    Membre chevronné

    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
    Points : 1 752
    Points
    1 752
    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 éprouvé

    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
    Points : 923
    Points
    923
    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 extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    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 éprouvé
    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
    Points : 1 066
    Points
    1 066
    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 chevronné

    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
    Points : 1 752
    Points
    1 752
    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 éprouvé
    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
    Points : 1 066
    Points
    1 066
    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 chevronné

    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
    Points : 1 752
    Points
    1 752
    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 chevronné

    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
    Points : 1 752
    Points
    1 752
    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

  9. #9
    Membre chevronné

    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
    Points : 1 752
    Points
    1 752
    Par défaut
    Comme pickle ne semble pas permettre de travailler avec des fichiers binaires, je vais garder cPickle. C'est une première sécurité. Il faudra que j'en ajoute une autre comme cela est proposé ici : http://nadiana.com/python-pickle-insecure .

    Merci à tous.

  10. #10
    Membre éprouvé
    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
    Points : 1 066
    Points
    1 066
    Par défaut
    Citation Envoyé par rambc Voir le message
    Quant l'usage de fichier binaire, cela n'y change rien à l'affaire.
    Sous linux, non, de fait.
    Sous Windows, tu risques d'avoir des surprises un jour ou l'autre. En effet, il remplace les sauts de ligne standards "\n" par "\r\n" en mode texte, et si mes souvenirs sont justes.

  11. #11
    Membre chevronné

    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
    Points : 1 752
    Points
    1 752
    Par défaut
    Citation Envoyé par Antoine_935 Voir le message
    Sous linux, non, de fait.
    Sous Windows, tu risques d'avoir des surprises un jour ou l'autre. En effet, il remplace les sauts de ligne standards "\n" par "\r\n" en mode texte, et si mes souvenirs sont justes.
    Si tu parles des fichiers TXT, je fais en sorte d'utiliser des méthodes multi-os.

    Pour les fichiers binaires je commence à peine à en avoir besoin. Sont-ce ces derniers qui risquent de causer des problèmes ?

  12. #12
    Membre extrêmement actif
    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
    Points : 1 658
    Points
    1 658
    Par défaut
    Antoine935 a raison: quand on enregistre (sur disque dur je veux dire) un texte sous Windows, ce dernier écrit toutes les fins de lignes ’\r\n’ même si le texte ne comporte que des ’\n’.

    Mais ceci peut être empêché en enregistrant le texte en mode binaire.




    Pour un texte qu’on n’a pas soi-même enregistré avec cette précaution, un code source capté sur internet par exemple, le texte peut très bien comporter des fins de lignes ’\r\n’.

    Cependant il n’y a pas de souci non plus, parce que Python est par défaut en mode Universal Newline qui transforme à la lecture n’importe quelle fin de ligne (’\n’ ou ’\r\n’ ou \r’ ) en ’\n’ uniquement.

    Cf la PEP 278:

    Universal newline support is enabled by default, but can be disabled during the configure of Python.
    (...)
    Any line ending in the input file will be seen as a '\n' in Python, so little other code has to change to handle universal newlines.



    Le seul souci causé par le comportement effronté de Windows est si on enregistre un texte en mode non binaire et qu’on cherche à balader le pointeur de fichier avec f.tell() et f.seek() en se fondant sur la connaissance de ce qu’on a enregistré. Ça ne marche pas car il y a des caractères ’\r’ en plus dans le fichier enregistré qui faussent le décompte des caractères après la première ligne.

  13. #13
    Membre chevronné

    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
    Points : 1 752
    Points
    1 752
    Par défaut
    Merci pour ces précisions.

  14. #14
    Membre chevronné

    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
    Points : 1 752
    Points
    1 752
    Par défaut
    Les tests précédents étaient mauvais en ce sens qu'ils utilisaient au passage la création de la liste. J'ai repris les codes ci-dessus en ajoutant le test du module shelve. J'espère ne pas avoir fait de fautes.
    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
    #!/usr/bin/env python
    #coding=utf-8
     
    from time import clock
    import pickle, cPickle, shelve
     
    # The following script makes a little comparison between
    # the use of pickle, cPickle and shelve in a very simple context.
     
    timeMemo = {'pickle' : [0, 0], 'cpickle' : [0, 0], 'shelve' : [0, 0]}
     
    i_max = 10000
    theTitles = ['Title ' + str(i) for i in range(1, i_max)]
     
    print '=== PICKLE ==='
     
    timeStart = clock()
    with open("test.txt", 'w') as f:
        for oneTitle in theTitles:
            pickle.dump(oneTitle, f)
    timeEnd = clock()
    timeMemo['pickle'][0] = timeEnd-timeStart
     
    timeStart = clock()
    with open("test.txt", 'r') as f:
        try:
            while True:
                oneVar = pickle.load(f)
                #print oneVar
        except:
            pass
    timeEnd = clock()
    timeMemo['pickle'][1] = timeEnd-timeStart
     
     
    print '=== CPICKLE ==='
     
    timeStart = clock()
    with open("testBis.txt", 'wb') as f:
        for oneTitle in theTitles:
            cPickle.dump(oneTitle, f, cPickle.HIGHEST_PROTOCOL)
    timeEnd = clock()
    timeMemo['cpickle'][0] = timeEnd-timeStart
     
    timeStart = clock()
    with open("testBis.txt", 'rb') as f:
        try:
            while True:
                oneVar = cPickle.load(f)
                #print oneVar
        except:
            pass
    timeEnd = clock()
    timeMemo['cpickle'][1] = timeEnd-timeStart
     
     
    print '=== SHELVE ==='
     
    timeStart = clock()
    d = shelve.open('test.dbm')
    numTitle = 1
    for oneTitle in theTitles:
        d[str(numTitle)] = oneTitle
        numTitle += 1
    d.close()
    timeEnd = clock()
    timeMemo['shelve'][0] = timeEnd-timeStart
     
    timeStart = clock()
    d = shelve.open('test.dbm')
    for i in xrange(1, i_max):
        oneVar = d[str(i)]
        #print oneVar
    d.close()
    timeEnd = clock()
    timeMemo['shelve'][1] = timeEnd-timeStart
     
     
    for oneMethod in timeMemo.keys():
        print oneMethod,
        print '\n\tEcriture : ', timeMemo[oneMethod][0] ,'   Lecture : ', timeMemo[oneMethod][1]
    Avec i_max = 100, j'ai obtenu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    cpickle 
    	Ecriture :  0.0    Lecture :  0.0
    pickle 
    	Ecriture :  0.01    Lecture :  0.0
    shelve 
    	Ecriture :  0.02    Lecture :  0.0
    Avec i_max = 10000, j'ai obtenu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    cpickle 
    	Ecriture :  0.02    Lecture :  0.02
    pickle 
    	Ecriture :  0.12    Lecture :  0.22
    shelve 
    	Ecriture :  0.31    Lecture :  0.28
    Avec i_max =1000000, j'ai obtenu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    cpickle 
    	Ecriture :  1.74    Lecture :  1.65
    pickle 
    	Ecriture :  11.91    Lecture :  21.33
    shelve 
    	Ecriture :  54.33    Lecture :  35.75
    Cela semble rassurant car cPickle gagne les tests. En résumé, je conseillerais cPickle dans un cadre d'enregistrement-lecture "séquentiel". Quant à shelve il est très pratique car il met à jour les données dynamiquement.

    A titre personnel, j'utiliserais peut-être shelve pour stocker un système de type 'uneAbréviation' ---> 'Texte associé à l'abréviation' car cela me semble plus simple à utiliser, et je doute qu'un humain puisse retenir plus d'une centaine d'abréviations.

    Pour valider mon choix, j'ai fait le test suivant où l'on cherche une variable particulière :
    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
    #!/usr/bin/env python
    #coding=utf-8
     
    from time import clock
    import cPickle, shelve
     
    # The following script makes a little comparison between
    # the use of pickle, cPickle and shelve in a very simple context.
     
    # He we test the reading of one single value. We choose to find the last one
    # because that's the more cossuming in the case of cPickle.
    # Here we want to see if shelve is faster than cPickle.
     
    timeMemo = {'cpickle' : 0, 'shelve' : 0}
     
    i_max = 100
    i_toFind = i_max
    theTitles = ['Title ' + str(i) for i in range(1, i_max)]
    titleToFind = 'Title ' + str(i_toFind)
     
    print '=== CPICKLE ==='
     
    print "Creation"
    with open("testBis.txt", 'wb') as f:
        for oneTitle in theTitles:
            cPickle.dump(oneTitle, f, cPickle.HIGHEST_PROTOCOL)
     
    print "Recherche"
    timeStart = clock()
    with open("testBis.txt", 'rb') as f:
        try:
            while True:
                oneVar = cPickle.load(f)
                #print oneVar
                if oneVar == titleToFind:
                    break
        except:
            pass
    timeEnd = clock()
    timeMemo['cpickle'] = timeEnd-timeStart
     
     
    print '=== SHELVE ==='
     
    print "Creation"
    d = shelve.open('test.dbm')
    numTitle = 1
    for oneTitle in theTitles:
        d[str(numTitle)] = oneTitle
        numTitle += 1
    d.close()
     
    print "Recherche"
    timeStart = clock()
    d = shelve.open('test.dbm')
    oneVar = d[str(i_max)]
    d.close()
    timeEnd = clock()
    timeMemo['shelve'] = timeEnd-timeStart
     
     
    for oneMethod in timeMemo.keys():
        print oneMethod,
        print '\n\tTrouvee : ', timeMemo[oneMethod]
    Avec i_max = 200, j'ai obtenu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    cpickle 
    	Trouvee :  0.0
    shelve 
    	Trouvee :  0.01
    Avec i_max = 1000, j'ai obtenu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    cpickle 
    	Trouvee :  0.0
    shelve 
    	Trouvee :  0.01
    Avec i_max =100000, j'ai obtenu :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    cpickle 
    	Trouvee :  0.19
    shelve 
    	Trouvee :  0.01
    L'emploi de shelve pour mon cadre d'utilisation reste donc très acceptable.

    Par contre, avec i_max =1000000, la méthode utilisée avec shelve ne marche pas. Finalement shelve est à utiliser pour son côté facile d'emploi avec surtout la possibilité de créer-modifier dynamiquement les données (ce qui n'est pas faisable directement avec cPickle).

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 17/04/2015, 13h32
  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, 12h06
  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, 11h49
  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, 16h40
  5. Réponses: 6
    Dernier message: 02/09/2003, 16h12

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