Semaine 2 · Jour 4 · 420-SN1

LIRE ET ÉCRIRE
DES FICHIERS

Faire entrer - et ressortir - les donnees de la foret : CSV et Excel

Les vraies donnees vivent dehors

Jusqu'ici, on tapait les donnees dans le code : pratique pour deux ou trois valeurs.

Mais les releves de terrain (des centaines de lignes !) vivent dans des fichiers. Lire un fichier = faire entrer ces donnees dans le programme sans les retaper.

🤖 Tout se met a tourner tout seul

Une fois la lecture des donnees automatisee, le programme peut produire a la chaine de nouveaux fichiers et meme des bases de donnees volumineuses - sans plus jamais retaper une valeur a la main.

Ecrit une fois, reutilise toujours

Un programme scientifique utile sait ouvrir un carnet de terrain, lire chaque ligne, et en extraire les valeurs.

Le code reste léger

Mille mesures restent dans le fichier, pas collées dans le programme : le code reste court et lisible.

Réutilisable demain

Le même programme tourne sur d'autres valeurs plus tard : on change le fichier, pas le code.

Écrit une fois

On écrit le programme une seule fois, puis on le relance sur chaque nouveau carnet de terrain.

Deux formats a connaitre

Fichier .txt

Texte brut, une information par ligne. Simple, direct, lisible par n'importe qui.

Fichier .csv

Valeurs separees par des virgules. Une grille comme un tableur : une ligne par observation, une colonne par variable.

🍄
# champignons.txt pleurottes bolets blancs champignons de paris pieds de moutons portobellos
# foret.csv espece,hauteur,age erable,12,40 pin,18,65
+ le format tableur .xlsx (Excel) : meme idee en grille, lu et ecrit avec pandas (voir plus loin).

Colab : où sont mes fichiers ?

{x}
🔍
📁
🕐
Fichiers ⬆️ 🔄
📁 sample_data
📁 drive
📄 foret.csv
📍 /content
1. Clique l'icône dossier 📁 (à gauche)
2. /content = ton dossier de travail
3. Bouton ⬆️ téléverser pour y déposer un fichier
4. sample_data = exemples · drive = ton Google Drive

Le panneau de fichiers (icône dossier, à gauche) montre /content : le dossier où ton programme travaille. open("foret.csv") cherche le fichier juste là.

Attention : /content est éphémère

📁 /content
📄 foret.csv
déconnexion
ou redémarrage
📁 /content
(vide !)

Les fichiers téléversés dans /content vivent sur une machine temporaire. Dès que la session se déconnecte ou redémarre (inactivité, environ 90 min), ils disparaissent - il faut les re-téléverser.

Les répertoires : /content (travail, éphémère) · /content/sample_data (exemples) · /content/drive/MyDrive (ton Drive, lui, permanent une fois monté).

Récupérer un fichier sans le re-téléverser

# 1. Depuis le web : telecharge dans /content !wget https://.../foret.csv # 2. Monter ton Google Drive (permanent !) from google.colab import drive drive.mount("/content/drive") open("/content/drive/MyDrive/foret.csv") # 3. Choisir un fichier de ton ordinateur from google.colab import files files.upload()

Trois façons d'amener un fichier dans Colab : !wget le télécharge du web, drive.mount branche ton Drive (rien ne se reperd !), files.upload() ouvre une fenêtre de choix. Pour garder tes données entre deux séances, le Drive est le plus sûr.

Ouvrir le carnet : with open

with open("foret.csv") as fichier: contenu = fichier.read() print(contenu)

with ouvre le fichier ET le referme tout seul a la fin du bloc - meme si une erreur survient. .read() lit tout le contenu d'un coup et le range dans une chaine de caracteres.

Tout d'un coup, ou ligne par ligne ?

Tout d'un coup : .read()
with open("foret.csv") as fichier: contenu = fichier.read() print(contenu) # une seule grosse chaine
Ligne par ligne : for
with open("foret.csv") as fichier: for ligne in fichier: print(ligne.strip())

.read() charge tout le fichier d'un coup dans une chaine - simple pour un petit fichier. La boucle ligne par ligne n'en garde qu'une a la fois - indispensable pour les gros fichiers. .strip() enleve le retour de ligne invisible colle au bout de chaque ligne.

Le \n invisible et .strip()

"erable,12,40\n"  # le retour de ligne est colle au bout
⬇️ .strip()
'erable,12,40'
❌ print(ligne)
erable,12,40
 
pin,18,65
 
une ligne vide en trop a chaque fois
✅ print(ligne.strip())
erable,12,40
pin,18,65
propre, comme attendu

\n est un seul caractere (le retour a la ligne) que Python garde au bout de chaque ligne lue : invisible a l'oeil, mais bien la. .strip() enleve les espaces et les retours de ligne colles au debut et a la fin - d'ou le reflexe ligne.strip() avant de decouper ou de comparer.

Reboucler sur le contenu de read()

"espece,hauteur,age\nerable,12,40\npin,18,65"
⬇️ .splitlines()
'espece,hauteur,age'
'erable,12,40'
'pin,18,65'
with open("foret.csv") as fichier: contenu = fichier.read() # une grosse chaine for ligne in contenu.splitlines(): # decoupe a chaque \n print(ligne)

read() donne tout en un seul bloc de texte, avec des retours de ligne \n invisibles au bout de chaque ligne. .splitlines() le recoupe en une liste de lignes, sur laquelle on peut alors boucler. (contenu.split("\n") fait presque pareil.)

Separer les colonnes : split

with open("foret.csv") as fichier: for ligne in fichier: champs = ligne.strip().split(",") print(champs) # ['erable', '12', '40']

.split(",") coupe la ligne a chaque virgule et donne une liste de champs. Le premier champ est champs[0], le deuxieme champs[1], et ainsi de suite.

Décortiquer une ligne

"erable,12,40"
⬇️ .split(",")
'erable'
espece · [0]
'12'
hauteur · [1]
'40'
age · [2]
with open("foret.csv") as fichier: entete = next(fichier) # saute la ligne de titres for ligne in fichier: champs = ligne.strip().split(",") espece = champs[0] # reste du texte hauteur = float(champs[1]) # converti en nombre ! age = int(champs[2])

Où atterrit chaque morceau ?

🔄
Un tour de boucle
= une ligne = une observation (un arbre)
for ligne in fichier:
📦
Une variable
= un seul champ (une case)
hauteur = float(champs[1])
📋
Un tableau (liste)
= la ligne découpée, ou une colonne entière
champs = ['erable','12','40']
🗃️
Un dictionnaire (hashmap)
= associer une clé à une valeur
arbres = {"erable": 12}

Le réflexe : une ligne = un tour de boucle. Un champ seul va dans une variable ; la ligne entière dans un tableau ; et pour retrouver une valeur par son nom (l'espèce → sa hauteur), un dictionnaire.

Le format roi : une liste de dictionnaires

arbres = [] for ligne in fichier: champs = ligne.strip().split(",") arbres.append({ "espece": champs[0], "hauteur": float(champs[1]), "age": int(champs[2]), })
[
{
  "espece"  : 'erable'
  "hauteur" : 12.0
  "age"     : 40
}
{
  "espece"  : 'pin'
  "hauteur" : 18.0
  "age"     : 65
}
]

Une liste dont chaque case est un dictionnaire : une ligne du fichier = une fiche {cle: valeur}. On lit ensuite arbres[0]["hauteur"] pour la hauteur du premier arbre. C'est le format le plus pratique pour analyser un tableau de donnees.

Sinon, chaque ligne s'efface

À chaque tour de boucle, la variable est écrasée par la ligne suivante. Si tu ne ranges la valeur nulle part ailleurs, à la fin il ne reste que la dernière ligne - tout le reste est perdu !

❌ Rien garde : perdu
for ligne in fichier: champs = ligne.strip().split(",") hauteur = float(champs[1]) print(hauteur) # 18.0 -> juste la DERNIERE !
✅ Dans une liste : garde
hauteurs = [] # AVANT la boucle for ligne in fichier: champs = ligne.strip().split(",") hauteurs.append(float(champs[1])) print(hauteurs) # [12.0, 18.0, ...]

La liste se cree avant la boucle (vide), puis .append(...) y ajoute une valeur a chaque tour : c'est ainsi qu'on garde toutes les donnees pour les analyser ensuite.

Trois write, et voilà l'entête dans le fichier

Le code : 3 × write()
with open("rapport.txt", "w") as fichier: fichier.write("========================================\n") fichier.write(" RAPPORT DU RECENSEMENT - FORET\n") fichier.write("========================================\n")
Le fichier produit →
rapport.txt ======================================== RAPPORT DU RECENSEMENT - FORET ========================================

Chaque fichier.write(...) dépose une ligne ; le \n à la fin passe à la ligne suivante. Les deux barres de = et le titre se retrouvent exactement tels quels dans rapport.txt - le fichier garde à la lettre ce qu'on lui a écrit. Sans \n, tout serait collé sur une seule ligne.

Le piège : write() n'est pas magique comme print()

❌ Ce qui plante
fichier.write(" Hauteur moyenne :", round(moyenneHauteur, 2), "m")
TypeError: write() takes exactly
one argument (3 given)
✅ La règle de write()
# UNE seule chaine, et QUE du texte fichier.write(" Hauteur moyenne : 14.2 m\n") # pas de virgules, pas de nombre brut, # pas de \n ajoute tout seul

print(...) est magique : il accepte plusieurs morceaux séparés par des virgules, met les espaces, transforme les nombres en texte et saute la ligne tout seul. write(...), lui, est basique : il veut une seule chaîne de texte, rien d'autre. Des virgules → TypeError. Un nombre brut comme round(moyenneHauteur, 2) → erreur aussi (c'est un nombre, pas du texte). Et pas de \n automatique : à toi de le mettre. Deux façons de s'en sortir →

Solution 1 : garder le print magique, viser le fichier

Le même print, avec file=fichier
with open("rapport.txt", "w") as fichier: print("========================", file=fichier) print(" RAPPORT - FORET", file=fichier) print(" Arbres recenses :", nombre, file=fichier) print(" Hauteur moyenne :", round(moyenneHauteur, 2), "m", file=fichier)
✅ On ne change presque rien
  • Les virgules fonctionnent encore
  • Les nombres s'écrivent tout seuls
  • Le retour de ligne est automatique
  • On ajoute juste , file=fichier à la fin de chaque print

Le truc le plus simple : on garde le print magique, on lui dit juste où aller avec file=fichier. Tout le confort de print (virgules, espaces, nombres, \n automatique) part directement dans le fichier au lieu de l'écran. Le geste à retenir : print(..., file=fichier).

Solution 2 : fabriquer la phrase, puis l'écrire

On colle le texte avec des f-strings
rapport = "" rapport += "========================\n" rapport += f" Arbres recenses : {nombre}\n" rapport += f" Hauteur moyenne : {round(moyenneHauteur, 2)} m\n" print(rapport) # a l'ecran with open("rapport.txt", "w") as fichier: fichier.write(rapport) # ET dans le fichier
✅ Une seule chaîne au bout
  • Le f"...{variable}..." glisse les nombres dans le texte
  • On met le \n nous-mêmes au bout de chaque ligne
  • À la fin, rapport est une seule grande chaînewrite() est content
  • Bonus : même texte à l'écran ET dans le fichier

Ici on fabrique d'abord toute la phrase dans une variable rapport, en collant les morceaux avec += et des f-strings (f"...{nombre}..." insère la valeur dans le texte). Quand rapport est prêt, c'est une seule chaîne : on peut l'print à l'écran et la write dans le fichier - exactement le même contenu. C'est ce que la majorité a fait. (La slide suivante montre une variante avec "\n".join(...).)

Deux chemins vers le même fichier

1 · print(..., file=fichier)
  • On garde le print tel quel, virgules comprises
  • Le plus rapide à débloquer quand write plante
  • Écrit au fur et à mesure, ligne par ligne
  • Pour aussi l'avoir à l'écran : refaire les print sans file=
2 · Concaténer puis write
  • On construit la chaîne d'abord (f-strings)
  • Un seul write(rapport) à la fin
  • Même texte à l'écran ET dans le fichier, sans se répéter
  • Demande de penser au \n soi-même

Les deux produisent exactement le même fichier. Choisis selon le besoin : débloquer vite un code déjà plein de print → ajoute file=fichier (Solution 1). Afficher à l'écran ET sauvegarder le même rapport sans tout écrire en double → concatène une fois, puis print + write (Solution 2). Le piège à ne jamais oublier : write() veut une seule chaîne de texte.

Écrire un fichier : produire un rapport

Construire le texte, puis l'enregistrer
lignes = [] lignes.append("=" * 40) lignes.append(" RAPPORT DU RECENSEMENT - FORET") lignes.append("=" * 40) lignes.append(" Arbres recenses : %d" % nombre) rapport = "\n".join(lignes) print(rapport) # a l'ecran with open("rapport-foret.txt", "w") as fichier: fichier.write(rapport) # ET dans un fichier
Le fichier produit : rapport-foret.txt
rapport-foret.txt ======================================== RAPPORT DU RECENSEMENT - FORET ======================================== Arbres recenses : 100 Hauteur moyenne : 14.2 m Plus haut : 27.4 m (pin) ========================================

Même recette que la lecture, à l'envers : on ouvre en mode "w", puis .write(...) dépose le texte dans le fichier. L'astuce : on accumule les lignes dans une liste, on les colle avec "\n".join(...), puis on écrit le tout d'un coup. C'est exactement l'entête du rapport du Projet 2 : le même rapport est affiché à l'écran ET sauvegardé pour Maya. ⚠ Le mode "w" écrase le fichier existant.

Ne pas réinventer la roue

BIBLIOTHÈQUES
DE FORMATS DE FICHIERS

csv · pandas · Excel · JSON - chaque format a son outil tout fait

Un outil specialise : import csv

import csv with open("foret.csv") as fichier: lecteur = csv.reader(fichier) for rangee in lecteur: print(rangee)

La bibliotheque csv fait le decoupage proprement - meme quand un champ contient une virgule ou des guillemets. On importe une bibliotheque pour ne pas reinventer la roue.

Écrire un CSV : 2 méthodes

À la main : .write()
with open("resultat.csv", "w") as fichier: fichier.write("espece,hauteur\n") fichier.write("erable,12\n")
Proprement : csv.writer
import csv with open("resultat.csv", "w", newline="") as fichier: redacteur = csv.writer(fichier) redacteur.writerow(["espece", "hauteur"]) redacteur.writerow(["erable", 12])

Pour créer un fichier, on l'ouvre en mode "w" (write). .write() écrit du texte brut - à toi de placer les virgules et le \n (retour de ligne). csv.writer le fait proprement : writerow transforme une liste en ligne CSV. ⚠ Le mode "w" écrase le fichier existant - utilise "a" pour ajouter à la suite.

pandas : lire et écrire un CSV

Lire
import pandas as pd tableau = pd.read_csv("foret.csv") print(tableau.head())
Écrire
# apres tes calculs... tableau.to_csv("resultat.csv", index=False)

Quand les données sont déjà en grille, pandas lit et écrit un CSV en une seule ligne. read_csv charge tout dans un tableau (DataFrame) ; to_csv le réenregistre. index=False évite d'ajouter une colonne de numéros.

Excel aussi : read_excel

import pandas as pd tableau = pd.read_excel("foret.xlsx") # lecture tableau.to_excel("resultat.xlsx", index=False) # ecriture

Le format tableur .xlsx (Excel, LibreOffice) se lit et s'écrit exactement comme un CSV avec pandas : read_excel et to_excel. Dans Colab, tout est déjà installé - aucun pip nécessaire.

Bonus : un .xlsx peut contenir plusieurs feuilles - on en choisit une avec sheet_name="Feuille1".

Et si le fichier est sur le web ?

# ✗ open ne parle PAS au reseau with open("https://.../foret.csv") as fichier: ... # FileNotFoundError !
# ✓ urlopen va chercher sur le web import urllib.request adresse = "https://.../foret.csv" with urllib.request.urlopen(adresse) as reponse: contenu = reponse.read().decode("utf-8")

open ne sait lire que les fichiers sur ton disque. Pour un fichier sur le web, il faut un outil qui parle au reseau : urlopen garde la meme forme with ... as, mais ouvre une connexion au lieu d'un fichier. Raccourci : open = disque, urlopen = reseau.

Bonus (vu au jour des tableaux) : numpy et pandas savent lire une adresse directement, ex. pandas.read_csv(adresse) accepte une URL comme un chemin local.

Bonnes pratiques

A RETENIR

  • Toujours utiliser with : le fichier se referme seul
  • Appeler .strip() pour nettoyer les fins de ligne
  • Sauter la ligne d'en-tete si besoin : next(fichier)
  • Convertir les nombres : int(...) ou float(...) - le fichier ne contient que du texte

Un fichier CSV ne contient que des chaines de caracteres. Pour faire des calculs, on doit convertir les valeurs numeriques apres la lecture.

A TOI DE JOUER

Cree un fichier foret.csv et lis-le dans ton calepin - lis chaque ligne, decoupe les colonnes, affiche les valeurs.

colab.research.google.com

AU TRAVAIL !

Seance 2-4 : ouvre le fichier de la foret, lis ses lignes, range les donnees
⤺ Refermer le diaporama