Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Register
  • Sign in
  • PYTHON - Atelier MatPlotLib PYTHON - Atelier MatPlotLib
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
  • Issues 0
    • Issues 0
    • List
    • Boards
    • Service Desk
    • Milestones
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Terraform modules
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar

La forge institutionnelle d'INRAE étant en production depuis le 10 juin 2025, nous vous recommandons d'y créer tous vos nouveaux projets.

  • Poulard Christine
  • PYTHON - Atelier MatPlotLibPYTHON - Atelier MatPlotLib
  • Wiki
  • AtelierB2_Lire_un_fichier

AtelierB2_Lire_un_fichier · Changes

Page history
Update AtelierB2_Lire_un_fichier authored Mar 12, 2021 by Poulard Christine's avatar Poulard Christine
Hide whitespace changes
Inline Side-by-side
AtelierB2_Lire_un_fichier.md
View page @ c91441dc
...@@ -5,70 +5,95 @@ De toutes façons, il faut savoir lire les données dans un fichier, donc c'est ...@@ -5,70 +5,95 @@ De toutes façons, il faut savoir lire les données dans un fichier, donc c'est
### B2) lire un fichier texte et extraire l'information ### B2) lire un fichier texte et extraire l'information
Vous trouverez du code déjà écrit dans le fichier Python visu_chronique.py, avec la fonction lecture_qj0_to_ts écrite pour lire des fichiers de débit journalier dans un des formats de la base Hydro2. Vous trouverez du code déjà écrit dans le fichier Python visu_chronique.py, avec la fonction lecteur_qj0_to_ts écrite pour lire des fichiers de débit journalier dans un des formats de la base Hydro2.
Vous êtes invités à vous approprier ce code, vous pouvez tester les instructions dans la console comme on a fait précédemment, et essayer de réécrire votre propre fonction. Normalement, le code est commenté, et vous êtes invités à vous approprier ce code. N'hésitez pas à tester les instructions dans la console comme on a fait précédemment, et essayer de réécrire votre propre fonction.
Il existe des méthodes performantes pour lire des fichiers structurés (colonnes nommées et lignes), notamment dans pandas et seaborn (read_csv). Ici, le fichier à un format qui se prête moyennement bien aux lectures en bloc, et on va donc travailler à l'ancienne. Il existe des méthodes performantes pour lire des fichiers structurés (colonnes nommées et lignes), notamment dans pandas et seaborn (read_csv). Ici, le fichier à un format qui se prête moyennement bien aux lectures en bloc, et on va donc travailler à l'ancienne.
Au passage, on va manipuler plusieurs notions utiles de Python. . Au passage, on va manipuler plusieurs notions utiles de Python. .
#### a) Définir un nom de fichier et lire ce fichier #### a) Définir le chemin vers le fichier
Pratique recommandée pour ouvrir un fichier : "with open(nom_fichier, 'r') as alias_du_fichier" La fonction **lecteur_qj0_to_ts** prend comme argument un chemin complet, répertoire+fichier.
=> notion de "context manager" qui garantit que le fichier se fermera à la fin du bloc d'instructions, quoi qu'il arrive
Pour mieux comprendre les instructions de "découpage" des lignes (split) et leur transcription en dates et valeurs, manipulez dans la console la chaîne " QJO;B2220010;19680627;7330.000;C;9;"
``` python Plusieurs solutions pour définir ce chemin :
ligne_lue_dans_le_fichier = "QJO;B2220010;19680627;7330.000;C;9;" **1) je tape le chemin en clair dans le code**, avec des slash / et pas de backslash, qui est un code d'échappement.
```
Si besoin, on fera un topo sur les dictionnaires, un type de conteneur central en python. ``` python
# j'entre directement le chemin sous forme de chaîne de caractère comme argument
Une fois la fonction écrite, il faut l'exécuter avec un chemin comme argument.
Plusieurs solutions :
1) je tape le chemin en clair dans le code, avec des slash / et pas de backslash :
ts = lecteur_qj0_to_ts("C:/WorkSpace/2020-BaO_MultiDSpa/Migrateurs/Meuse/B2220010_qj_hydro2_2019.txt") ts = lecteur_qj0_to_ts("C:/WorkSpace/2020-BaO_MultiDSpa/Migrateurs/Meuse/B2220010_qj_hydro2_2019.txt")
éventuellement : # deuxième solution, je passe par une variable
chemin_complet = "C:/WorkSpace/2020-BaO_MultiDSpa/Migrateurs/Meuse/B2220010_qj_hydro2_2019.txt" chemin_complet = "C:/WorkSpace/2020-BaO_MultiDSpa/Migrateurs/Meuse/B2220010_qj_hydro2_2019.txt"
ts = lecteur_qj0_to_ts(chemin_complet) ts = lecteur_qj0_to_ts(chemin_complet)
2) je demande à l'utilisateur de saisir le nom au clavier
chemin_complet= input("Entrez le chemin complet vers le fichier de données") ```
**2) je demande à l'utilisateur de saisir le nom au clavier**
La commande **input** permet de demander à l'utilisateur de saisir une réponse au clavier
``` python
chemin_complet= input("Entrez le chemin complet vers le fichier de données :")
# j'ai intérêt à vérifier si le fichier existe # j'ai intérêt à vérifier si le fichier existe
from pathlib import Path from pathlib import Path
# explication : j'utilise la méthode is_file de Path sur l'objet nom_fichier converti en Path # explication : j'utilise la méthode is_file de Path sur l'objet nom_fichier converti en Path
if Path.is_file(Path(chemin_complet)): if Path.is_file(Path(chemin_complet)):
ts = lecteur_qj0_to_ts(chemin_complet) ts = lecteur_qj0_to_ts(chemin_complet)
else: else:
print("chemine ", chemin_complet, " non valide") print("chemin ", chemin_complet, " non valide")
3) j'utilise une fonction de Tkinter ```
from tkinter.filedialog import askopenfilename On peut écrire une boucle **while** qui repose la question tant que le chemin n'est pas valide.
**3) j'utilise une fonction de Tkinter**
``` python
from tkinter.filedialog import askopenfilename
chemin_complet= askopenfilename() # ouverture d'une fenêtre explorateur chemin_complet= askopenfilename() # ouverture d'une fenêtre explorateur
```
C'est une utilisation "vite fait sur le gaz" d'une fonnctionnalité qui s'utilise normalement avec une interface graphique. En l'absence de cette interface, Tkinter va se débrouiller et ouvrir quand même une interface dans un coin, qu'il faudra refermer.
On verra si nécessaire comment définir proprement une interface, mais cela sort du cadre de ce premier atelier.
#### b) Ouvrir le fichier et le lire ligne par ligne
Un code vous est déjà proposé.
Pratique recommandée pour ouvrir un fichier : "**with** open(nom_fichier, 'r') as alias_du_fichier"
=> **with** introduit un **"context manager"** qui garantit que le fichier se fermera à la fin du bloc d'instructions, quoi qu'il arrive.
Ensuite, on va lire les lignes avec alias_du_fichier.readline().
Dans le code proposé, on va d'abord lire les lignes une à une jusqu'à en trouver une qui contienne un mot-clé.
Ensuite, on lit toutes les autres grâce à une simple boucle **for ligne_lue in alias_du_fichier**, qui lira les lignes une par une jusqu'à la fin. Grâce au context manager, le fichier sera fermé proprement à la fin du bloc de code.
=> figure selon 2 modalités, une fois à partir de listes issues d'un dictionnaire, et une autre fois avec le wrapper de pandas (mon_objet_pandas.plot) Chaque ligne récupérée sous forme de chaîne de caractères, **string**, et stockée dans une variable que nous avons appelée **ligne_lue**.
b) Extraire l'information utile : "parser" les lignes #### c) Extraire l'information utile : "parser" les lignes
Il nous faut maintenant extraire l'information des lignes lues.
On a supposé que nos données ne sont pas assez bien bien structurées pour utiliser les instructions modernes de type "read_csv" (du module pandas ou seaborn par exempe).
Ceci est un parsing "à l'ancienne", ligne par ligne. Un peu pénible, certes, cette étape permet de réaliser des vérifications et de décomposer des éléments, ainsi que de manipuler des notions de liste et string. On réalise ici un parsing "à l'ancienne", ligne par ligne. Un peu pénible, certes, mais cette étape permet de réaliser des vérifications et de décomposer des éléments, ainsi que de manipuler des notions de liste et string.
Pour une lecture "en bloc", avec des données bien structurées, voir les instructions modernes de type "read_csv" (du module pandas ou seaborn par exempe).
Les commentaires du code + la diapo doivent vous guider. Les commentaires du code + la diapo doivent vous guider.
Pour comprendre, définissez une chaîne de caractères (string) nommée ligne dans la console Pour mieux comprendre les instructions de "découpage" des lignes (split) et leur transcription en dates et valeurs, manipulez dans la console la chaîne " QJO;B2220010;19680627;7330.000;C;9;"
ligne = "QJO;B2220010;19680705;5280.000;C;9;"
# Effectuez ensuite des tests, par exemple :
"QJO" in ligne #retourne un boléen, vrai/faux (en Python, True.False, avec une majuscule)
ligne.splitee = ligne.split(";") # ligne_splitee est une LISTE de STRINGS
ligne.splitee[1] # élément d'indice 1, est-ce le premier ???
ligne.splitee[2][0:4] # string composé des caractères d'indices 0 à 4 EXCLU de l'élément d'indice 2
valeur_numerique = float(ligne.splitee[3] )
# Création d'un dictionnaire ``` python
ligne_lue_dans_le_fichier = "QJO;B2220010;19680627;7330.000;C;9;"
```
Effectuez ensuite des tests, par exemple
``` python
"QJO" in ligne_lue_dans_le_fichier # retourne un booléen, vrai/faux (en Python, True ou False, avec une majuscule)
ligne_splitee = ligne_lue_dans_le_fichier.split(";") # ligne_splitee est une LISTE de STRINGS
ligne_splitee[1] # élément d'indice 1, est-ce le premier ???
ligne_splitee[2][0:4] # string composé des caractères d'indices 0 à 4 EXCLU de l'élément d'indice 2
valeur_numerique = float(ligne_splitee[3] )
```
#### d) stockage de l'information dans un dictionnaire
Si besoin, on fera un topo sur les dictionnaires, un type de conteneur central en python.
Le dictionnaire associe des clés à des valeurs.
On utilisera plusieurs fois des dictionnaires, on va donc découvrir ici une manière de créer un dictionnaire, et les principales instructions utiles.
La **clé** doit être d'un type NON-MUTABLE* (voir notes) ; évidemment, si la clé changeait on perdrait la relation clé-valeur. Les types string, datetime, chiffre... conviennent. Une liste ne convient pas.
La **valeur associée** peut être de n'importe quel type, y compris des conteneurs, et peut en théorie varier d'une clé à l'autre (mais en pratique il vaut mieux se tenir à un même type, ou au minimum à des types qui partagent les méthodes que l'on va devoir leur appliquer dans la suite...
``` python
# définition d'un dictionnaire ; entre accolades # définition d'un dictionnaire ; entre accolades
dictionnaire_main = {1:"un", 2:"deux", 3: "trois", 4:"quatre", 5: "cinq"} # dictionnaire avec couples clé: valeur dictionnaire_main = {1:"un", 2:"deux", 3: "trois", 4:"quatre", 5: "cinq"} # dictionnaire avec couples clé: valeur
mon_dictionnaire = dict() # dictionnaire vide mon_dictionnaire_vide = dict() # dictionnaire vide
mon_dictionnaire [clef] = valeur # j'ajoute une entrée (j'ajoute des entrées comme je veux) mon_dictionnaire[clef] = valeur # j'ajoute une entrée à un dictionnaire existant (j'ajoute des entrées comme je veux)
# la variable clef doit être d'un type NON-MUTABLE (voir notes) ; les types string, datetime, chiffre... conviennent
# la variable valeur peut être de n'importe quel type, y compris des conteneurs
mon_dictionnaire[clef] #renvoie la valeur mon_dictionnaire[clef] #renvoie la valeur
mon_dictionnaire.keys() # vue des clés ; ce n'est pas une liste mais c'est un itérable mon_dictionnaire.keys() # vue des clés ; ce n'est pas une liste mais c'est un itérable
for clef in mon_dictionnaire.keys() : for clef in mon_dictionnaire.keys() :
...@@ -78,27 +103,47 @@ for clef in mon_dictionnaire: ...@@ -78,27 +103,47 @@ for clef in mon_dictionnaire:
print("clé = ", clef) print("clé = ", clef)
cle_de_sol in mon_dictionnaire.keys() # booléen, vrai si cle_de_sol est une ces clés cle_de_sol in mon_dictionnaire.keys() # booléen, vrai si cle_de_sol est une ces clés
mon_dictionnaire.values() # vue des valeurs ; ce n'est pas une liste mais c'est un itérable mon_dictionnaire.values() # vue des valeurs ; ce n'est pas une liste mais c'est un itérable
mon_dictionnaire.items() # vue des couples (clé, valeur) ; c'est un iterable dont les éléments sont des tuples mon_dictionnaire.items() # vue des couples (clé, valeur) ; c'est un itérable* dont les éléments sont des tuples
for clef, valeur in mon_dictionnaire.items() : for clef, valeur in mon_dictionnaire.items() :
print("clé = ", clef, " et valeur = ", valeur) print("clé = ", clef, " et valeur = ", valeur)
```
#### e) tracé à partir du dictionnaire, puis à partir d'une structure pandas Series
# tracé à partir du dictionnaire, puis à partir d'une structure pandas Series Ensuite, on compare 2 manière de tracer le graphique q(t) : d'abord à partir du dictionnaire ; pour cela il faut extraire du dictionnaire la liste_des_dates et la liste_des_q.
Ensuite, on compare 2 manière de tracer le graphique q(t) : La doc indique que les dictionnaires n'existaient pas quand matplotlib a été développé, et il n'a pas été conçu au départ pour accepter directement un dictionnaire comme argument, ni même les vues keys et values d'un dictionnaire : il faut les convertir en **liste** d'abord pour les utiliser comme arguments.
``` python
liste_des_dates= list(mon_dictionnaire.keys() ) # on convertit la vue en liste
liste_des_q = list(mon_dictionnaire.values() )
plt.plot(liste_des_dates, liste_des_q)
plt.plot(liste_des_dates, liste_des_q), avec liste_des_dates = clés du dictionnaire et liste_des_a = valeurs # ou directement
plt.plot(list(mon_dictionnaire.keys()),list(mon_dictionnaire.values())
```
On va tester le wrapper de pandas (méthode **mon_objet_pandas.plot()**)
Pour cela, on doit d'abord créer un objet de type pandas Series avec les données, sur lequel on appliquera la méthode plot : ma_series.plot().
on convertit le dictionnaire en objet pandas Series et on applique la méthode plot : ma_series.plot() La conversion est facile, puisque le module pandas, lui, accepte un dictionnaire comme argument.
On introduit dans ce 2e cas un type de courbe "en créneaux" qui convient mieux à des valeurs moyennes journalières. On introduit dans ce 2e cas un type de courbe "en créneaux" qui convient mieux à des valeurs moyennes journalières.
Comment exécuter la fonction ? Remarque : comment exécuter une fonction à la fois pour suivre le déroulement de l'atelier ?
Deux solutions : C'est vrai qu'un notebook est bien pratique pour avancer étape par étape.
Ici, on va mettre en oeuvre l'une ou l'autre de ces deux techniques :
1) écrire les instructions dans le "corps du programme", précédé ici d'un test pour activer certaines sous-parties au fur et à mesure du déroulé 1) écrire les instructions dans le "corps du programme", précédé ici d'un test pour activer certaines sous-parties au fur et à mesure du déroulé
2) travailler dans la console et utiliser le fichier comme un module : 2) travailler dans la console et utiliser le fichier comme un module. La ligne après les définitions de fonctions, donc en début de corps de programme, et qui vous intrigue peut-être est justement là pour permettre d'utiliser le fichier comme module sans déclencher l'exécution des instructions.
``` python
if __name__ == '__main__':
# bloc d'instructions qui ne s'exécute que si le fichier est exécuté en temps que programme principal
#donc qui ne s'exécutera pas si le fichier est importé comme module d'un autre programme
```
Voilà ce qui doit se passer dans la console :
``` python
from Atelier_MatPlotLib_2021_part1 import lecteur_qj0_to_ts from Atelier_MatPlotLib_2021_part1 import lecteur_qj0_to_ts
from datetime import datetime, timedelta from tkinter.filedialog import askopenfilename # parce qu'on en a besoin dans la console
from tkinter.filedialog import askopenfilename
import matplotlib.pyplot as plt
chemin_complet = askopenfilename() chemin_complet = askopenfilename()
ts = lecteur_qj0_to_ts(chemin_complet) ts = lecteur_qj0_to_ts(chemin_complet)
```
Clone repository
  • AtelierB1_Graphiques_simples
  • AtelierB2_Lire_un_fichier
  • AtelierC
  • Atelier_D_carte
  • Atelier_D_carte_a_partir_de_fichiers_binaires
  • Atelier_E_longues_series
  • Atelier_G_widgets
  • Atelier_clic_afficher
  • Atelier_clics
  • Cartes focus sur le redimensionnement
  • GUI avec QT
  • La doc avec Sphinx
  • Lexique
  • Point Théorie Subplots
  • Pour les contributeurs
View All Pages