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 :

Imbrication de boucles


Sujet :

Python

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 62
    Par défaut Imbrication de boucles
    Bonjour,
    je ne comprends pas pourquoi la 2 ème boucle ne s'exécute qu'une fois (celle ventes). Une fois le premier passage effectué, ligneA reste bloqué sur la dernière valeure prise dans ventes. Du coup, la boucle ne se relance pas pour la deuxième valeur de ligne. Comment faire un "RAZ" pour le pointeur de lecture du fichier ventes ?

    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
    #! /usr/bin/env python
    #-*- coding: iso-8859-15 -*-
     
    import csv
    #print csv.__doc__ 
    #print dir(csv)
    articles = csv.reader(open("TRAV288906-traitement4.CSV","rb"),delimiter=';')
    ventes = csv.reader(open("TRAV4_D00_003.CSV","rb"),delimiter=';')
    newarticles = csv.writer(open("trav2w.csv","wb"),delimiter=';')
    for ligne in articles:
        if ligne:
            numart = int(ligne[0])
        for ligneA in ventes:
            if ligneA:
                numart_vt = int(ligneA[0])
            if numart == numart_vt:
                print "Oky"                             
    newarticles.close()
    ventes.close()
    articles.close()
    François

  2. #2
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonsoir vega95,

    Cela ne viens pas de ta boucle (si tu donne tout le code).

    Pourquoi ne pas déplacer ton ventes = csv.reader(open("TRAV4_D00_003.CSV","rb"),delimiter=';') / ventes.close() dans for ligne in articles: pour tester ?

    @+

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 62
    Par défaut trop gros le fichier
    J'y avais songé mais le pb c'est que le fichier ventes en question fait 1,2 Go. Je ne peux pas l'ouvrir et fermer n fois sous peine d'y passer un certain temps

    François

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 62
    Par défaut suite
    j'ai aussi essayé un ventes.seek(0) mais il me répond :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AttributeError: '_csv.reader' object has no attribute 'seek'

    François

  5. #5
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    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 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Je ne connais pas le module cvs, mais voilà 2 idées à tenter:

    1- ouvre le fichier ventes séparément:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    fv = open("TRAV4_D00_003.CSV","rb")
    ventes = csv.reader(fv,delimiter=';')
    et applique fv.seek(0) juste avant le début de boucle "for ligneA in ventes". Cela ne marchera que si en fin de boucle les fonctions cvs.Reader ne ferme pas le fichier fv par un fv.close().

    2- regarde dans la notice du module cvs du côté de DictReader. Ça a l'air de transformer le fichier en dictionnaire. Mais je ne sais pas s'il s'agit de le mettre en mémoire ou d'en normaliser l'accès comme un dictionnaire.

    Tyrtamos

  6. #6
    Membre expérimenté
    Profil pro
    Inscrit en
    Mai 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2008
    Messages : 141
    Par défaut
    Salut,

    une autre piste : si tu ne travailles que sur les premières colonnes de chacun des fichiers csv, tu peux récupérer tes infos sous forme de liste :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    articles = [int(ligne[0]) for ligne in csv.reader(open("TRAV288906traitement4.CSV","rb"),delimiter=';') if ligne]
     
    ventes = [int(ligne[0]) for ligne in csv.reader(open("TRAV4_D00_003.CSV","rb"),delimiter=';') if ligne]
    Je présume que tes fichiers, bien qu'ayant une taille monstrueuse, comportent assez peu de lignes et que la majorité de leur taille mémoire est justifiée par des infos annexes à ton problème.

    Je présume aussi que tu ne voudras jamais récupérer d'autres colonnes (genre : nom des articles, quantités vendues, prix, etc.), même si cela peut se modifier assez vite.
    Après, si tu as à terme dee récupérer l'intégralité de tes fichiers, laisse tomber mon approche.

    Le fseek de Tyrtamos est très bien.

    Et le DictReader permet de lire chaque ligne en tant que dictionnaire, dont les index sont les titres des colonnes et les valeurs sont les valeurs des colonnes de la ligne.
    C'est un itérateur, et il va chercher tout seul les titres des colonnes.
    C'est intéressant, mais pas si on ne cherche qu'à récupérer la première colonne des fichiers.
    Mais je penserais à m'en servir, merci Tyrtamos.

    Dernier point : le module csv ne supporte pas l'encodage : cette info t'intéressera si tu veux récupérer des strings non-ASCII. => n'utilise pas csv pour cela !

    Bon courage !

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 62
    Par défaut super
    Merci pour vos réponses et idées. L'idée de Tyrtamos marche nickel

    Résolu donc

    merci,
    François

  8. #8
    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
    csv.reader(csvfile[, dialect='excel'][, fmtparam])
    Return a reader object which will iterate over lines in the given csvfile. csvfile can be any object which supports the iterator protocol and returns a string each time its next() method is called — file objects and list objects are both suitable.

    http://docs.python.org/library/csv.html#index-268


    Je ne sais pas pourquoi il est écrit
    « Return a reader object which will iterate »
    et non pas
    « Return an iterator »
    et si ce que retourne csv.reader() serait de quelque manière un peu ou bien différent d’un itérateur patenté.
    Mais il me semble que ce que retourne csv.reader() n’est rien d’autre qu’un itérateur pur jus.



    Or:

    iterable
    (....)
    Iterables can be used in a for loop and in many other places where a sequence is needed (zip(), map(), ...). When an iterable object is passed as an argument to the built-in function iter(), it returns an iterator for the object. This
    iterator is good for one pass over the set of values.

    iterator
    An object representing a stream of data. Repeated calls to the iterator’s next() method return successive items in the stream. When no more data are available a StopIteration exception is raised instead.
    At this point, the iterator object is exhausted and any further calls to its next() method just raise StopIteration again.
    Iterators are required to have an __iter__() method that returns the iterator object itself so every iterator is also iterable and may be used in most places where other iterables are accepted. One notable exception is code which attempts multiple iteration passes. A container object (such as a list) produces a fresh new iterator each time you pass it to the iter() function or use it in a for loop. Attempting this with an iterator will just return the same exhausted iterator object used in the previous iteration pass, making it appear like an empty container.

    http://docs.python.org/glossary.html#term-iterator



    Le problème vient donc à mon avis du fait que les variables articles, ventes et newarticles sont des itérateurs et ne peuvent être parcourus qu’une seule fois par une boucle.
    Ce qui se passe donc , c’est que l’itération for ligneA in ventes: , une fois faite ne peut pas être refaite.


    La solution est de faire des listes de ces variables.
    Définir ventes = list( csv.reader(open("TRAV4_D00_003.CSV","rb"),delimiter=';') )
    devrait solutionner le problème.



    Le code suivant démontre, me semble-t-il, la cause du probléme et cette solution la plus simple.

    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
    def f(x):  return 2*x + 0.4
    li = [ 12,'orange',34,('ui',345),23,24,25,{'lu':222,'lo':455},98,f,467,[1,24,23,5,47],90,34,99]
    print 'li =\n',li
    IT = iter(li)
    print '\nIT = iter(li)   type(IT) =',type(IT)
     
    print '\n\n-- Premiere boucle dans iterateur IT ---------------------'
    for i,x in enumerate(IT):
        if type(x)==type(1):
            try:  print IT.next()
            except:  pass
     
    print '-- Deuxieme boucle dans iterateur IT ---------------------'
    for j,u in enumerate(IT):
        if type(u)==type(1):
            try:  print IT.next()
            except:  pass
     
    print '\n\n============================================='
     
    it2 = iter(li)
    L = list(it2)
     
    print '-- Premiere boucle dans liste L ----------'
    for i,x in enumerate(L):
        if type(x)==type(1):
            try:  print L[i+1]
            except:  pass
     
    print '-- Deuxieme boucle dans liste L ----------'
    for i,x in enumerate(L):
        if type(x)==type(1):
            try:  print L[i+1]
            except:  pass
    J’ai aussi pensé qu’il serait peut ètre possible de les transformer en fonctions génératrices pour conserver l’avantage d’itérer sur quelque chose qui n’est pas effectivement créé en mémoire vive, mais ça a deux inconvénients:
    - je ne vois pas comment faire ça et je ne sais pas si ça corrigerait effectivement le problème (!)
    - il me semble qu’une fonction génératrice se base sur un conteneur qui est de toutes façons aussi “en dur“ dans la mémoire vive



    Plus simple mais pareillement avec un générateur qui est un itérateur particulier

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    gege = (x for x in xrange(50) if x%6==1)
     
    for u in gege:
        print u,
     
    print '\n================'
     
    for y in gege:
        print y+10,
    >>>
    1 7 13 19 25 31 37 43 49
    ================
    >>>


    Iterators in Python are a fundamental part of the language and in many cases go unseen as they are implicitly used in the for (foreach) statement, in list comprehensions, and in generator expressions.
    [ame]http://en.wikipedia.org/wiki/Iterator[/ame]


    On oublie cette importance à cause de ceci:

    When using iterables, it is usually not necessary to call iter() or deal with iterator objects yourself. The for statement does that automatically for you, creating a temporary unnamed variable to hold the iterator for the duration of the loop.
    http://docs.python.org/glossary.html#term-iterator




    NB:

    J’aimerais bien arriver à savoir s’il y a une importance quelconque à ce qu’il soit écrit
    « Return a reader object which will iterate »
    et non pas
    « Return an iterator »dans la définition de csv.reader().......

  9. #9
    Membre Expert
    Homme Profil pro
    Inscrit en
    Mars 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2007
    Messages : 941
    Par défaut
    Citation Envoyé par eyquem Voir le message
    J’aimerais bien arriver à savoir s’il y a une importance quelconque à ce qu’il soit écrit
    « Return a reader object which will iterate »
    et non pas
    « Return an iterator »dans la définition de csv.reader().......
    Il suffisait de regarder un peu plus loin dans la documentation
    http://docs.python.org/library/csv.html#reader-objects

    C'est un itérateur avec quelques attributs en plus...

  10. #10
    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
    Merci dividee. Comme quoi, la puce ne m’avait pas gratté à l’oreille sans raison.

    --------------------------

    Si on regarde d’un peu près l’algorithme, on voit qu’il est faiblard, pour ne pas dire plus....


    On peut déjà faire une première condensation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
        for ligneA in ventes:
            if ligneA:
                numart_vt = int(ligneA[0])
            if numart == numart_vt:
                print "Oky" 
     
        # transformé en
     
        for ligneA in ventes:
            if ligneA and numart == int(ligneA[0]):
                print "Oky"

    Si ligneA est vide , le test numart == int(ligneA[0]) n’est même pas commencé d’être effectué, donc cette écriture ne pose pas de problème tout en éliminant un nom de variable.



    Ensuite comme numart a été défini par numart = int(ligne[0]) , il s’ensuit qu’on fait comparer int(ligne[0]) défini auparavant à int(ligneA[0])
    À moins que ligne[0] et ligneA[0] aient des blancs, si leurs entiers doivent être égaux c’est que ligne[0] et ligneA[0] doivent être égales (en tant que chaînes). D’où la simplification:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    for ligne in articles:
        if ligne:
            numart = ligne[0]
        for ligneA in ventes:
            if ligneA and numart == ligneA[0]:
                print "Oky"
    À ce point, on regarde:

    - on parcourt les lignes de articles les unes aprés les autres

    - si une ligne n’est pas vide, numart devient ligne[0]
    PUIS on cherche dans TOUTES les lignes de ventes la ligneA (non vide) telle que ligneA[0] ==numart

    - et si ligne est vide, alors.......... on cherche dans TOUTES les lignes de ventes la ligneA (non vide) telle que ligneA[0] ==numart
    Bien sûr il s’agit du numart de la ligne précédente
    On va donc faire print “Oky“ une deuxième fois pour une raison identique

    - au passage, on remarque qu’on fait for ligneA in ventes: pour chacune de toutes les lignes de articles
    C’est à dire que s’il y a 500 lignes d’articles (vides ou non) et 200 lignesA de ventes, on va faire faire prendre à ligne et ligneA 500 x 200 = 100000 valeurs ! Dont une partie pour rien puisque c’est pour certaines lignes vides une opération blanche.

    Il faut donc au moins décaler
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    for ligne in articles:
        if ligne:
            numart = int(ligne[0])
            for ligneA in ventes:
                if ligneA and numart == int(ligneA[0]):
                    print "Oky"
    On va cette fois comparer du genre 400 lignes x 200 lignesA.







    Mais même ainsi cela reste insatisfaisant: c’est même complétement mauvais de parcourir de façon réitérée dans la totalité d’un fichier ventes pour chaque ligne non vide d’un fichier articles.

    La solution est évidente: il faut parcourir une seule fois articles et une seule fois ventes et mettre les données dans un dictionnaire de façon adaptée.
    On ne doit pas être loin d’utiliser le DictReader disponible dans le module csv.

    À toi de jouer, vega95

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2008
    Messages : 62
    Par défaut optimisation
    Merci Eyquem, je vais regarder çà de prêt et en tirer les conséquences pour mon programme

    François

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

Discussions similaires

  1. [MySQL] Imbrication de boucles
    Par Vinuto dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 05/06/2012, 12h17
  2. Imbrication de boucles For
    Par dominos dans le forum Débuter
    Réponses: 4
    Dernier message: 03/04/2010, 18h53
  3. [MySQL] Imbrication de boucle if /else et while
    Par jmtrivia dans le forum PHP & Base de données
    Réponses: 5
    Dernier message: 09/04/2009, 13h11
  4. imbrication de boucle (exemple :d'upload)
    Par new-dmx dans le forum Langage
    Réponses: 2
    Dernier message: 01/09/2008, 16h18
  5. Encore problème d'imbrication de boucles
    Par flora806 dans le forum Langage
    Réponses: 4
    Dernier message: 21/02/2008, 16h25

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