14 - CSV

Introduction

Les données du monde réel sont souvent organisées en tables : un tableur, un carnet de notes, un relevé bancaire, un fichier d’élèves. Le format CSV (pour Comma Separated Values, littéralement « valeurs séparées par des virgules ») est le format le plus simple et le plus universel pour stocker et échanger ces données tabulaires.

Un fichier CSV est un fichier texte ordinaire dans lequel chaque ligne correspond à un enregistrement (une ligne du tableau) et chaque valeur est séparée de la suivante par un délimiteur, le plus souvent une virgule ou un point-virgule.

Pourquoi le CSV est-il si répandu ? Parce qu’il est lisible par n’importe quel éditeur de texte, importable dans n’importe quel tableur (Excel, LibreOffice Calc, Google Sheets) et manipulable facilement en Python grâce au module csv.

Structure d’un fichier CSV

Considérons le fichier employes.csv dont voici le contenu :

prénom,nom,département,mois de naissance
Jean,Valjean,comptabilité,novembre
Yves,Farge,ressources humaines,mars
Ada,Lovelace,informatique,décembre

La première ligne est l’en-tête : elle donne le nom de chaque champ (colonne). Les lignes suivantes sont les enregistrements : chaque ligne contient les données d’un employé.

Visualisons ce fichier sous forme de tableau :

prénomnomdépartementmois de naissance
JeanValjeancomptabiliténovembre
YvesFargeressources humainesmars
AdaLovelaceinformatiquedécembre

Remarques importantes :

  • le délimiteur n’est pas toujours la virgule. En France, on utilise souvent le point-virgule (;) car la virgule sert de séparateur décimal ;
  • si une valeur contient elle-même le délimiteur, on l’entoure de guillemets : "Dupont, Jean".

Lecture avec csv.reader()

Le module csv de Python fournit la fonction reader() qui lit le fichier ligne par ligne et renvoie chaque enregistrement sous forme de liste :

import csv

with open('employes.csv', encoding='utf-8') as fichier:
    lecteur = csv.reader(fichier, delimiter=',')
    for ligne in lecteur:
        print(ligne)
['prénom', 'nom', 'département', 'mois de naissance']
['Jean', 'Valjean', 'comptabilité', 'novembre']
['Yves', 'Farge', 'ressources humaines', 'mars']
['Ada', 'Lovelace', 'informatique', 'décembre']

Chaque ligne est une liste de chaînes de caractères. On accède aux valeurs par leur indice : ligne[0] pour le prénom, ligne[1] pour le nom, etc.

Pour sauter la ligne d’en-tête, on utilise la fonction next() :

import csv

with open('employes.csv', encoding='utf-8') as fichier:
    lecteur = csv.reader(fichier, delimiter=',')
    next(lecteur)  # saute l'en-tête
    for ligne in lecteur:
        print(f'{ligne[0]} {ligne[1]} travaille en {ligne[2]}')
Jean Valjean travaille en comptabilité
Yves Farge travaille en ressources humaines
Ada Lovelace travaille en informatique

Lecture avec csv.DictReader()

La fonction DictReader() est souvent plus pratique : elle renvoie chaque enregistrement sous forme de dictionnaire, en utilisant les noms de la première ligne comme clés.

import csv

with open('employes.csv', encoding='utf-8') as fichier:
    lecteur = csv.DictReader(fichier, delimiter=',')
    for ligne in lecteur:
        print(f'{ligne["prénom"]} {ligne["nom"]} est né(e) en {ligne["mois de naissance"]}')
Jean Valjean est né(e) en novembre
Yves Farge est né(e) en mars
Ada Lovelace est né(e) en décembre

L’avantage est évident : on accède aux valeurs par nom de colonne (ligne["prénom"]) au lieu d’un indice numérique (ligne[0]). Le code est plus lisible et plus robuste si l’ordre des colonnes change.

Écriture avec csv.writer()

Pour écrire des données dans un fichier CSV, on utilise csv.writer() :

import csv

employes = [
    ['prénom', 'nom', 'département', 'mois de naissance'],
    ['Alan', 'Turing', 'informatique', 'juin'],
    ['Donald', 'Knuth', 'informatique', 'janvier']
]

with open('nouveaux.csv', 'w', encoding='utf-8', newline='') as fichier:
    ecrivain = csv.writer(fichier, delimiter=',')
    for employe in employes:
        ecrivain.writerow(employe)

Le fichier nouveaux.csv contiendra :

prénom,nom,département,mois de naissance
Alan,Turing,informatique,juin
Donald,Knuth,informatique,janvier

Remarque importante : le paramètre newline='' dans open() est nécessaire pour éviter des lignes vides supplémentaires sous Windows.

Pour ajouter des lignes à un fichier existant, on ouvre le fichier en mode 'a' (pour append) au lieu de 'w' :

with open('employes.csv', 'a', encoding='utf-8', newline='') as fichier:
    ecrivain = csv.writer(fichier, delimiter=',')
    ecrivain.writerow(['Grace', 'Hopper', 'informatique', 'décembre'])

Écriture avec csv.DictWriter()

De même que DictReader() facilite la lecture, DictWriter() facilite l’écriture en permettant de travailler avec des dictionnaires au lieu de listes. Il faut préciser les noms des colonnes via le paramètre fieldnames, puis appeler writeheader() pour écrire la ligne d’en-tête :

import csv

employes = [
    {'prénom': 'Alan', 'nom': 'Turing', 'département': 'informatique'},
    {'prénom': 'Grace', 'nom': 'Hopper', 'département': 'informatique'}
]

with open('equipe.csv', 'w', encoding='utf-8', newline='') as fichier:
    colonnes = ['prénom', 'nom', 'département']
    ecrivain = csv.DictWriter(fichier, fieldnames=colonnes, delimiter=',')
    ecrivain.writeheader()             # écrit la ligne d'en-tête
    for employe in employes:
        ecrivain.writerow(employe)     # écrit un dictionnaire par ligne

Le fichier equipe.csv contiendra :

prénom,nom,département
Alan,Turing,informatique
Grace,Hopper,informatique

L’avantage par rapport à csv.writer() est le même que celui de DictReader() par rapport à csv.reader() : on manipule des noms de colonnes plutôt que des indices numériques, ce qui rend le code plus lisible.

Comparaison : reader() vs DictReader()

Pour choisir entre les deux approches, voici ce que chacune renvoie pour la même ligne du fichier employes.csv :

# Avec csv.reader() → une LISTE de chaînes
['Jean', 'Valjean', 'comptabilité', 'novembre']
# Accès par indice : ligne[2] → 'comptabilité'

# Avec csv.DictReader() → un DICTIONNAIRE
{'prénom': 'Jean', 'nom': 'Valjean', 'département': 'comptabilité', 'mois de naissance': 'novembre'}
# Accès par clé : ligne['département'] → 'comptabilité'

csv.reader() est suffisant pour les fichiers simples avec peu de colonnes. csv.DictReader() est préférable dès que le fichier a beaucoup de colonnes ou que l’on veut un code lisible et robuste face aux changements d’ordre des colonnes.

Charger un CSV dans une liste de dictionnaires

Un traitement courant consiste à charger l’intégralité d’un fichier CSV en mémoire, sous forme d’une liste de dictionnaires. Cela permet ensuite de filtrer, trier ou analyser les données facilement :

import csv

def charger_csv(nom_fichier):
    """Charge un fichier CSV et renvoie une liste de dictionnaires."""
    with open(nom_fichier, encoding='utf-8') as fichier:
        lecteur = csv.DictReader(fichier, delimiter=',')
        return list(lecteur)

donnees = charger_csv('employes.csv')
print(donnees)
[{'prénom': 'Jean', 'nom': 'Valjean', 'département': 'comptabilité', 'mois de naissance': 'novembre'},
 {'prénom': 'Yves', 'nom': 'Farge', 'département': 'ressources humaines', 'mois de naissance': 'mars'},
 {'prénom': 'Ada', 'nom': 'Lovelace', 'département': 'informatique', 'mois de naissance': 'décembre'}]

On peut ensuite filtrer les données :

# Tous les employés du département informatique
informaticiens = [e for e in donnees if e['département'] == 'informatique']
print(informaticiens)

Résumé des fonctions du module csv

FonctionRôleType renvoyé par ligne
csv.reader()Lecture ligne par ligneliste de chaînes
csv.DictReader()Lecture avec en-têtedictionnaire
csv.writer()Écriture ligne par ligne
csv.DictWriter()Écriture avec en-tête