Manipuler un fichier
Fermémamiemando Messages postés 33506 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 31 janvier 2025 - 17 nov. 2022 à 19:42
- Manipuler un fichier
- Fichier rar - Guide
- Comment réduire la taille d'un fichier - Guide
- Comment ouvrir un fichier epub ? - Guide
- Ouvrir un fichier .bin - Guide
- Comment ouvrir un fichier docx ? - Guide
8 réponses
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
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
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
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.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre questionModifié 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
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
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
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
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.