Manipuler un fichier

Fermé
LALO_5656 Messages postés 21 Date d'inscription mardi 8 novembre 2022 Statut Membre Dernière intervention 4 juillet 2023 - Modifié le 8 nov. 2022 à 14:28
mamiemando Messages postés 32948 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 février 2024 - 17 nov. 2022 à 19:42

Bonjour à tous,

J'ai plus de 100 fichiers txt que je voudrais ouvrir un par un.

  • Dans chaque fichier ouvert je voudrais copier certaines chaines de caractères qui se trouvent sur des lignes différentes et les coller dans le fichier csv (rapport).
  • Dans tous mes fichiers, les données à copier se trouvent sur les mêmes lignes

Voila le code que j'ai essayé d'écrire mais qui marche pas:

import parse
with fichier as fichier:
    ligne = fichier.readlines()
    ligne10 = parse.parse("STRT.M {}                                 :START DEPTH", ligne[10])
    ligne16 = parse.parse("STCK.    {}                               :STACK", ligne[16])
import csv
header = ["Operateur", "Début rdc", "Fin rdc", "Type", "Prof"]
with open(rapport, "w") as csv_file:
    writer = csv.writer(csv_file, delimiter=",")
    writer.writerow(header)

Je suis vraiment débutant en python. Quelqu'un a une idée ? D'avance merci !

A voir également:

8 réponses

mamiemando Messages postés 32948 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 février 2024 7 722
10 nov. 2022 à 10:44

Bonjour,

Néanmoins sais-tu comment je peux coller cette information dans mon fichier csv au niveau de la colonne Prof ? 

Je suppose que ce que tu veux reporter dans la colonne Prof est le résultat de m.group(1) ?

Il faudrait spécifier comment tu remplis chaque colonne en fonction de la ligne lue. Ce que je te conseille, c'est de faire une liste de dictionnaires, tels que leur clé coïncident avec les noms de colonnes. Appelons dans ce qui suit entries la liste de dictionnaire et entry le dictionnaire courant.

Ci-dessous un exemple de code qui devrait te débloquer :

import csv, re
from io import StringIO
from pprint import pprint

RE_STRT_M = re.compile("STRT\.M\s+(\w+)\s+:START DEPTH")
RE_STCK = re.compile("STCK\.\s+(\w+)\s+:STACK")

def make_dummy_input_file(i) -> StringIO:
    lines = [f"line{i}" for i in range(20)]
    lines[10] = f"STRT.M   plop{i}     :START DEPTH"
    lines[16] = f"STCK.    pouet{i}      :STACK"
    return StringIO("\n".join(lines))

def extract_strt_m(s: str) -> str:
    m = RE_STRT_M.match(s)
    return m.group(1) if m else None

def extract_stck(s: str) -> str:
    m = RE_STCK.match(s)
    return m.group(1) if m else None

def extract_data(lines) -> dict:
    strt_m = extract_strt_m(lines[10])
    stck = extract_stck(lines[16])
    return {
        "strt_m" : strt_m,
        "stck"   : stck,
    }

def entries_to_csv(entries: list, f_out, *cls, **kwargs) -> bool:
    if not entries:
        return False
    writer = csv.writer(f_out, *cls, **kwargs)
    keys = sorted(entries[0].keys())
    writer.writerow(keys)
    for entry in entries:
        writer.writerow([entry.get(k) for k in keys])
    return True

def print_file(filename):
    with open(filename, "r") as f:
        print("".join(f.readlines()))

def main():
    entries = list()
    for i in range(10):
        # Generate dummy data to parse
        input_data = make_dummy_input_file(i)
        #print("-" * 80)
        #print(input_data.getvalue())

        # Read the i-th file
        lines = input_data.readlines()
        entry = extract_data(lines)
        entry["index"] = i
        entries.append(entry)

    print("=" * 80)
    pprint(entries)

    filename_csv = "toto.csv"
    with open(filename_csv, "w") as f_out:
        entries_to_csv(entries, f_out)

    print("=" * 80)
    print_file(filename_csv)

main()

Il faut commencer par lire le main : je génère 10 StringIO (qui sont des chaînes qui se comportent comme des fichiers, donc on peut appliquer dessus readlines comme tu le fais avec des fichiers normaux) avec la fonction make_dummy_input_file. Tu peux décommenter les fonctions print pour voir que leur contenu est conforme à tes fichiers (donc, des données à extraire lignes 10 et 16). Les "fichiers" ont un contenu différent en fonction de leur index i (qui commence à 0). Par exemple le 9-ème "fichier" contient :

line0
line1
line2
line3
line4
line5
line6
line7
line8
line9
STRT.M   plop8     :START DEPTH
line11
line12
line13
line14
line15
STCK.    pouet8      :STACK
line17
line18
line19

Ensuite, j'extrais de chacun de ces "fichiers" leurs données avec extract_data, qui en cascade appelle les fonctions permettant d'extraire les valeurs que tu veux récupérer. Selon la nature de ces données, note qu'il faudra peut-être adapté les expressions_régulières RE_*. Mais comme à ce stade, ce n'est pas spécifié, j'ai supposé que les valeurs à extraire étaient dans les deux cas un mot composé de caractères alphanumériques.

Comme je ne sais pas comment tu veux reporter les valeurs extraites dans les colonnes, j'ai considéré que le fichier csv contenait une ligne par fichier, et trois colonnes (l'index du fichier i, et une colonne par valeur extraite).

Une fois le code exécuté, on voit qu'on est parvenu à extraire les valeurs de nos 10 fichiers d'entrées :

================================================================================
[{'index': 0, 'stck': 'pouet0', 'strt_m': 'plop0'},
 {'index': 1, 'stck': 'pouet1', 'strt_m': 'plop1'},
 {'index': 2, 'stck': 'pouet2', 'strt_m': 'plop2'},
 {'index': 3, 'stck': 'pouet3', 'strt_m': 'plop3'},
 {'index': 4, 'stck': 'pouet4', 'strt_m': 'plop4'},
 {'index': 5, 'stck': 'pouet5', 'strt_m': 'plop5'},
 {'index': 6, 'stck': 'pouet6', 'strt_m': 'plop6'},
 {'index': 7, 'stck': 'pouet7', 'strt_m': 'plop7'},
 {'index': 8, 'stck': 'pouet8', 'strt_m': 'plop8'},
 {'index': 9, 'stck': 'pouet9', 'strt_m': 'plop9'}]
================================================================================
index,stck,strt_m
0,pouet0,plop0
1,pouet1,plop1
2,pouet2,plop2
3,pouet3,plop3
4,pouet4,plop4
5,pouet5,plop5
6,pouet6,plop6
7,pouet7,plop7
8,pouet8,plop8
9,pouet9,plop9

Bonne chance

1
mamiemando Messages postés 32948 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 février 2024 7 722
Modifié le 8 nov. 2022 à 14:36

Bonjour,

Peux-tu donner un exemple minimal de fichier d'entrée et de fichier de sortie ?

Dans le premier extrait de code, si j'ai bien compris ce que tu veux faire, tu veux extraire des lignes 10 et 16 la chaîne de caractère située après STRT.M et STCK. ? Personnellement j'utiliserais le module re et une expression régulière.

import re

s = "STRT.M   pouet     :START DEPTH"
r = re.compile("STRT.M\s+(\w+)\s+:START DEPTH")
m = r.match(s)
if m:
    print(m.group(1)) # Affiche "pouet"

Et dans le second, comme header n'est pas défini je ne sais pas ce que tu veux faire.

Bonne chance

0
LALO_5656 Messages postés 21 Date d'inscription mardi 8 novembre 2022 Statut Membre Dernière intervention 4 juillet 2023 1
Modifié le 10 nov. 2022 à 10:05

Bonsoir merci infiniment. Ça m'a beaucoup aidé. Néanmoins sais-tu comment je peux coller cette information dans mon fichier csv au niveau de la colonne Prof ? Encore merci

0
LALO_5656 Messages postés 21 Date d'inscription mardi 8 novembre 2022 Statut Membre Dernière intervention 4 juillet 2023 1
Modifié le 15 nov. 2022 à 17:50

Bonjour mamiemando, merci pour vos réactions.

Désolé de vous déranger encore plus, mais je n'arrive vraiment pas à adapter le code à mes besoins. En clair, voici

J'ai plus de cent fichiers numérotés ainsi :

  • I16T04-001
  • ...
  • I16T04-121

Dans mon fichier de sortie, la première colonne comporte le nom du fichier ouvert.

0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
mamiemando Messages postés 32948 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 février 2024 7 722
Modifié le 15 nov. 2022 à 18:14

Bonjour,

Je n'ai pas pu accéder au fichier de sortie (il faut une autorisation) mais j'ai pu voir le fichier d'entrée. Il serait beaucoup plus simple pour tout le monde que tu copies colle directement le contenu de tes fichiers dans tes message.

I16T04-001

#------------------------------------------------
~Version Information Section
VERS.     2.0     :  CWLS Log Ascii Standard Version
WRAP.  NO  :  One Line Per Depth
#------------------------------------------------
#------------------------------------------------
~Well Information Section
#MNEM.UNIT        VALUE.NAME                     DESCRIPTION
#------------------------------------------------
STRT.M   6.70                                    :START DEPTH
STOP.M   -0.80                                   :STOP DEPTH
STEP.M   -0.10                                   :STEP
NULL.    -999.25                                 :NULL VALUE
COMP.    foat                                    :COMPAGNIE
WELL.   TAMR                                     :FORAGE
STCK.    GGWL_7800                               :STACK
PHA.     1                                       :N° PHASE
RUN.     2                                       :N° RUN
CTRY.    NEANT                                   :PAYS
PROV.    YAOUT                                   :PROVINCE
FLD.     ARTO                                    :CHANTIER
STKP.    DECENTERED                              :POS. DU STACK
LONG.M                                           :LONGITUDE
LAT.M                                            :LATITUDE
EGL.M                                            :ALTITUDE
CSYS.                                            :SYS. COORDO.
DREF.    CASING                                  :PROF. DE REF.
BS.MM    76.2                                    :DIAM. THEORIQUE
TDD.M                                            :PROF. FOREUR
TDL.M                                            :PROF. DIAG.
DFT.     BENTONITE                               :TYPE DE FLUIDE
MSS.     MUD PIT                                 :ORIGINE FLUIDE
DFD.GM3                                          :DENSITE
DFV.S                                            :VISCOSITE
DFLS.    NON                                     :PERTE
DFL.M3                                           :VOLUME
DFLV.M                                           :NIVEAU
DATE.    18/08/22                                :DATE DE DEBUT
END.     18/08/22                                :DATE DE FIN
DLAB.    18/08/22                                :STK AU FOND
DLAT.    18/08/22                                :STK EN SURFACE
AUTO.    Log started jeudi, août 18 2022  21:55  :
OPE.     samuel                                  :DIAGRAPHISTE
SRVC.    TANOUT                                  :DIAG. COMP.
UNIT.    1500                                    :N° BAIE
COME.    OPEN HOLE                               :ENV. DE MESURE
UWI.     0000     :UNIQUE WELL ID

Ensuite il y a plusieurs choses à corriger dans le script que je t'ai donné :

  • Plus besoin de générer des fichiers d'exemples, on lit directement les vrais.
  • En python les listes sont indexées à partir de 0. Donc quand tu parles des lignes 10 et 16, il s'agit en python des éléments 9 et 15 dans la liste engendrée par f.readlines(). Une manière simple de déboguer et d'afficher la chaîne s traitée par extract_stck et extract_strt_m.
  • Il faut bien entendu adapter le main pour lire l'ensemble de tes fichiers. En admettant que le script toto.py et les fichiers d'entrées sont dans le même dossier :
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import csv, re, sys
from io import StringIO
from pprint import pprint

RE_STRT_M = re.compile("STRT\.M\s+(\S+)\s+:START DEPTH")
RE_STCK = re.compile("STCK\.\s+(\S+)\s+:STACK")

def extract_strt_m(s: str) -> str:
    print(f"extract_strt_m({s})")
    m = RE_STRT_M.match(s)
    return m.group(1) if m else None

def extract_stck(s: str) -> str:
    print(f"extract_stck({s})")
    m = RE_STCK.match(s)
    return m.group(1) if m else None

def extract_data(lines) -> dict:
    strt_m = extract_strt_m(lines[9])
    stck = extract_stck(lines[15])
    return {
        "strt_m" : strt_m,
        "stck"   : stck,
    }

def entries_to_csv(entries: list, f_out, *cls, **kwargs) -> bool:
    if not entries:
        return False
    writer = csv.writer(f_out, *cls, **kwargs)
    keys = sorted(entries[0].keys())
    writer.writerow(keys)
    for entry in entries:
        writer.writerow([entry.get(k) for k in keys])
    return True

def print_file(filename):
    with open(filename, "r") as f:
        print("".join(f.readlines()))

def main():
    entries = list()
    for filename in [
        f"I16T04-{i:03d}"
        for i in range(1, 122)
    ]:
        try:
            with open(filename, "r") as f:
                lines = f.readlines()
                entry = extract_data(lines)
                entry["filename"] = filename
                entries.append(entry)
            print(f"Processed {filename}")
        except Exception as e:
            print(f"Skipping {filename}: {e}", sys.stderr)

    filename_csv = "output.csv"
    with open(filename_csv, "w") as f_out:
        entries_to_csv(entries, f_out)

    print("=" * 80)
    print_file(filename_csv)

main()
  • Les expressions rationnelles que j'ai donné précédemment font l'hypothèse que le bloc à extraire était une valeur composées de lettres et de chiffres.
    • Or pour STCK, c'est une valeur décimale qui contient donc un ".". Elle n'était donc pas prise en compte. Je les ai donc relâchées toutes les deux en disant n'importe quelle séquence non vide de caractères autres que des espaces (\S+)
    • Si toutes les valeurs de STCK sont  des valeurs décimales, ça peut être une bonne idée de convertir ces chaînes en float, en particulier si tu as besoin de coder un filtrage (par exemple, je ne veux que les entrées dont STCK est supérieur à un certain seuil). Si tu exportes directement entries en csv, ça n'est pas nécessaire car le fichier csv restera le même. Si tu décides d'apporter cette correction, corrige la valeur retournée par extract_data :
    return {
        "strt_m" : strt_m,
        "stck"   : float(stck),
    }

Bonne chance

0
LALO_5656 Messages postés 21 Date d'inscription mardi 8 novembre 2022 Statut Membre Dernière intervention 4 juillet 2023 1
Modifié le 16 nov. 2022 à 12:26

 
Bonjour à tous,

Désolé, voici l'exemple de fichier de sortie avec les renseignements du premier fichier ouvert (I16T04-001) 

ID;STRT.M;WELL;STCK;FDL;BS.MM;DATE;OPE;UNIT
I16T04-001;6.7;TAMR;GGWL_7800;ARTO;76.2;18/08/2022;SAMUEL;1500
0
mamiemando Messages postés 32948 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 février 2024 7 722
16 nov. 2022 à 12:30

Bonjour,

As-tu testé et compris le code que je t'ai donné dans le message #5 ? Il te permet d'avoir les colonnes ID, STRT.M et STCK. As-tu des questions / remarques par rapport à ce code ?

Si tu es toujours bloqué : ton message #6 : comment sont obtenus le contenu des colonnes WLL, DDL, BS.MM, DATE, OPE, UNIT ?

Bonne chance

0
LALO_5656 Messages postés 21 Date d'inscription mardi 8 novembre 2022 Statut Membre Dernière intervention 4 juillet 2023 1
17 nov. 2022 à 17:27

Bonsoir effectivement ,je l'ai essayé mais mon fichier de sorti est vide.

Dans mon message #6 je ecris ces valeurs pour que vous voyez les restes de données à extraires

dans le premier fichier.

MERCI

0
mamiemando Messages postés 32948 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 février 2024 7 722
17 nov. 2022 à 19:42

Bonjour,

Chez moi le script marche donc je ne sais pas quoi te dire.

(mando@silk) (~) $ rm -f output.csv 

(mando@silk) (~) $ python3 toto.py
(mando@silk) (~) $ python3 toto.py 
extract_strt_m(STRT.M   6.70                                    :START DEPTH
)
extract_stck(STCK.    GGWL_7800                               :STACK
)
Processed I16T04-001
...
================================================================================
filename,stck,strt_m
I16T04-001,GGWL_7800,6.70

(mando@silk) (~) $ cat output.csv 
filename,stck,strt_m
I16T04-001,GGWL_7800,6.70


Et comme dtu ne dis pas comment remplir les colonnes te manquent, je ne vois pas trop comment t'aider.

0