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 :

Extraire données fichier texte [Python 2.X]


Sujet :

Python

  1. #1
    Membre régulier
    Inscrit en
    Juillet 2009
    Messages
    155
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 155
    Points : 77
    Points
    77
    Par défaut Extraire données fichier texte
    Bonjour le forum,

    Je recherche à extraire une liste d'information d'un fichier texte à la structure particulière. Les infos que je veux extraire se trouvent, dans ce fichier, après un certain mot (unique dans le fichier), et jusqu'à la prochaine ligne vide.
    Ainsi, pour récupérer l'info dont j'ai besoin, voici ce que j'ai imaginé :
    - Identifier le mot "balise",
    - Stocker les lignes suivantes dans une liste, tant que la ligne n'est pas vide.

    Et voici mon code qui marche "presque", au détail près qu'il reste sur la ligne du mot "balise", et ne sort donc jamais de la boucle while... (et donc ne marche pas^^)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    des = "\\......."
    lst_per = []
     
    with open(des, 'r') as fichier:
        for lines in fichier:
            if "ETENDUE=" in lines:
                while lines != "\n":
                    #print lines
                    lst_per.append(lines)

    Autant en algo ou dans d'autre langage, pas de problème, mais en Python, où je débute, je ne m'en sors pas...
    Je vois peut-être différentes solutions avec plusieurs boucles, ou des indices, etc.... mais m'appropriant petit à petit la philosophie de Python, je pressens qu'il y a moyen de faire ça de façon simple, propre, et concise....?

    Merci de votre aide.

  2. #2
    Membre éprouvé

    Homme Profil pro
    Ingénieur
    Inscrit en
    Août 2010
    Messages
    654
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2010
    Messages : 654
    Points : 1 150
    Points
    1 150
    Par défaut
    Salut,

    A la condition if, vous lancez une boucle while. Vous n'en sortez pas, car la condition lines != "\n" reste vrai. Vous ne passez à la ligne suivante que lorsque vous arrivez à la fin de votre boucle while, qui ne s'arrête pas tant que vous ne passez pas à une ligne suivante vide... Boucle sans fin. :)

    Voici un algorithme qui pourrait vous convenir:
    • On ouvre le fichier (ça c'est bon)
    • On défini une variable indiquant que l'on se trouve dans le bloc nous intéressant. Par exemple block = False
    • On initie une boucle, par exemple for, sur les lignes
    • Si dans la ligne le mot clé est présent, on passe block à vrai
    • Si block est vrai mais que la ligne est vide, c'est qu'on est arrivé à la fin. On passe block à faux, voir on force la sortie de la boucle
    • Si block est vrai et la ligne non vide, on la traite



    J

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 240
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 240
    Points : 36 696
    Points
    36 696
    Par défaut
    Salut,

    Citation Envoyé par discus23 Voir le message
    Autant en algo ou dans d'autre langage, pas de problème, mais en Python, où je débute, je ne m'en sors pas...
    Un algo. basique est de lire les lignes tant qu'on n'a pas rencontré le mot balise, puis de lire les lignes (et en faire ce qu'on veut) tant qu'on n'a pas rencontré de ligne vide.
    Ça s'écrit avec l'enchainement de deux boucles "while":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    tant que condition est fausse
            ligne = lire ligne
            condition = ligne contient balise ou ligne est vide
    Après on peut tout mettre dans la même boucle en utilisant un drapeau.


    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  4. #4
    Membre régulier
    Inscrit en
    Juillet 2009
    Messages
    155
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 155
    Points : 77
    Points
    77
    Par défaut
    Merci wiztricks.

    Je saisis un peu mieux mais je ne vois pas comment gérer les deux boucles While ?
    Cela veut dire aussi que la boucle For disparaît ?

    Et merci julien, je viens de voir la réponse également. Je vais me pencher dessus bien que cela semble sortir de mes capacités Python actuelle.

    Essayons !

  5. #5
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 678
    Points
    13 678
    Billets dans le blog
    1
    Par défaut
    Tu peux effectivement te passer de la boucle for. L'idée est de lire tant que tu ne rencontres pas la ligne avec la balise et de jeter le texte. Ensuite, tu lis jusqu'à trouver une ligne vide et de garder le texte. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    f = open('data.txt')
     
    line = f.readline()
     
    while line != 'BALISE:\n':
        print('Throw line: ', line)
        line = f.readline()
     
    print('Start keeping text')
     
    while line != '\n':
        print('Keep line: ', line)
        line = f.readline()
    Une question à se poser est de savoir si tu as plusieurs blocs (== plusieurs balises) dans un même fichier. Dans ce cas, une boucle for avec une mini machine d'états pourraient être plus lisibles. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    f = open('data.txt')
     
    in_block = False
     
    for line in f:
        if line == 'BALISE:\n':
            in_block = True
        elif line == '\n':
            in_block = False
     
        if in_block:
            print('Keep text: ', line)
        else:
            print('Throw text: ', line)

  6. #6
    Membre régulier
    Inscrit en
    Juillet 2009
    Messages
    155
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 155
    Points : 77
    Points
    77
    Par défaut
    Bonjour à tous, et merci pour vos conseils.

    En m'inspirant du code proposé par @Bktero, voici ce à quoi j'aboutis, et qui correspond bien à mes attentes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    with open(des, 'r') as fichier:
        line = fichier.readline()
        while line.find('ETENDUE=') != 0:
            print('Je jette: ', line)
            line = fichier.readline()
     
        while line != '\n':
            print('Je garde: ', line)
            line = fichier.readline()
    Merci !!

    Je n'avais pas conscience de la différence entre readline() et readlines().
    Ici, on utilise readline() pour lire la première ligne, puis on l'utilise à nouveau pour passer à la ligne suivante, et ainsi de suite, contrairement au for lines in fichier de mon code initial qui parcourt le fichier du début à la fin 'tout seul'. C'est bien ça ?

    Question bonus, plus pour progresser en Python que pour répondre au besoin initial :
    Admettons que je ne veuille afficher que les lignes comprises entre le mot balise et la prochaine ligne vide (sans le mot balise donc), il existe une façon propre de faire ça en Python ?

  7. #7
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 678
    Points
    13 678
    Billets dans le blog
    1
    Par défaut
    Il n'y a pas un 's' pour rien

    En effet, un for line in file va itérer sur toutes les lignes. A chaque tour, Python fait automatiquement la lecture de la ligne suivante. Tu pourrais faire exactement la même chose avec une boucle while qui fait un appel à readline() et s'arrête quand la ligne retournée est vide.

    Bonus : c'est pas presque déjà ce que fait ton code ? Quand la 1ere boucle se termine, line contient le mot balise. Et si tu lisais la première ligne après la balise avant de rentrer dans ta 2e boucle ?

  8. #8
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2019
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2019
    Messages : 2
    Points : 4
    Points
    4
    Par défaut
    Bonjour à tous,

    J'ai un problème similaire, même s'il n'est pas exactement le même. Je préfère d'abord poster ma question ici, mais j'ouvrirai un nouveau post si on m'indique que c'est plus approprié.

    J'ai aussi un fichier texte organisé "par blocs", avec à l'intérieur des info à récupérer. D'abord, je récupère un numéro contenu dans la 1ère ligne des blocs. J'utilise simplement la boucle "for line in file" et le module re pour récupérer le numéro contenu entre deux chaines de caractères reconnaissables. Bref, jusqu'ici tout fonctionne. A partir de là, et ce pour chaque numéro récupéré en début de ligne de blocs, il s'agit maintenant de récupérer des coordonnées de points, dont l'info est donnée à l'intérieur du bloc. Il s'agit alors de lire uniquement les lignes comprises entre la ligne courante (celle de laquelle on a récupéré le numéro) et la prochaine ligne qui contient le mot clé "</ELEM>" (cela constitue un "bloc"). Il s'agit donc de rester dans le même bloc ici parce que le fichier en question contient d'autres coordonnées de points, écrites à la fois dans d'autres blocs et même hors des blocs, et j'ai besoin de récupérer avec cohérence le numéro du bloc et les coordonnées des points que ce bloc contient.

    D'où mon problème : dans ma boucle principale "for line in file", je n'arrive pas à créer une boucle secondaire qui permette de lire uniquement entre la ligne courante de ma boucle "for line in file" et la ligne contenant le prochain mot clé "</ELEM>" (qui se trouve quelques lignes plus loin).


    Pour la suite, normalement je sais extraire les coordonnées dont j'ai besoin, mais je bloque sur la création de la boucle...


    Je vous remercie d'avance.

  9. #9
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 678
    Points
    13 678
    Billets dans le blog
    1
    Par défaut
    Salut,

    Il faut bien comprendre qu'une boucle for line in file lit toutes les lignes. Tu ne peux pas faire une second boucle à l'intérieur. Regarde mon message #5 et son 2e code avec la mini-machine d'états : je pense que c'est la meilleure façon pour toi de t'en sortir.

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 240
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 240
    Points : 36 696
    Points
    36 696
    Par défaut
    Salut,

    Citation Envoyé par aldimeola Voir le message
    D'où mon problème : dans ma boucle principale "for line in file", je n'arrive pas à créer une boucle secondaire qui permette de lire uniquement entre la ligne courante de ma boucle "for line in file" et la ligne contenant le prochain mot clé "</ELEM>" (qui se trouve quelques lignes plus loin).
    La différence est que vous avez ici plusieurs blocks, il faut itérer la solution un seul block décrite ici (2 boucles imbriquées dans une boucle imbriquée) ou faire fonctionner l'idée que le PO n'arrivait pas à faire fonctionner (son premier post):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    for line in f:
         si condition in line:
             for line in f:
                  tant que balise n'est pas dans ligne:
                         accumuler les lignes
    c'est une machine à état dans laquelle l'état est câblé dans le code.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  11. #11
    Membre régulier
    Inscrit en
    Juillet 2009
    Messages
    155
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 155
    Points : 77
    Points
    77
    Par défaut
    Encore merci @Bktero,

    Oui c'est "tout simplement" ça en effet. C'est d'ailleurs ce que j'avais fait mais pas avec la bonne indentation et ma boucle while ne sortait jamais.

    Résolu !

  12. #12
    Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Juillet 2019
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juillet 2019
    Messages : 2
    Points : 4
    Points
    4
    Par défaut
    Citation Envoyé par Bktero Voir le message
    Salut,

    Il faut bien comprendre qu'une boucle for line in file lit toutes les lignes. Tu ne peux pas faire une second boucle à l'intérieur. Regarde mon message #5 et son 2e code avec la mini-machine d'états : je pense que c'est la meilleure façon pour toi de t'en sortir.


    Merci Bktero, cela répond parfaitement à ma question, j'ai pu m'en sortir comme ça

    Bonne journée à tous.

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 02/06/2016, 08h57
  2. Extraire données fichier texte vers une matrice
    Par mygwel dans le forum MATLAB
    Réponses: 7
    Dernier message: 05/03/2009, 13h20
  3. [VBA-E] Récupération données fichier texte
    Par Theo28fr dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 20/07/2006, 09h08
  4. [VBA-E] Tableau de données <=> Fichier Texte
    Par P50 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 18/12/2005, 17h02
  5. Extraire données fichier txt
    Par philippef dans le forum Langage
    Réponses: 1
    Dernier message: 10/10/2005, 18h12

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