Le Module CSV

un pique-nique

Photo by Bruno /Germany de Pixabay

Nous avons vu dans les chapitres précédents que l'on pouvait utiliser le format CSV, qui est à la fois répandu et standard, pour enregistrer des données sur un disque et pour les récupérer aussi.

Ces lectures et écritures font appel massivement aux méthodes split et join et sont assez délicates à écrire. En informatique, le nombre d'instructions élémentaires du langage pour programmer est en réalité assez faible. Au niveau des instructions, quand on sait instancier des variables, faire des boucles, des tests, des fonctions et accéder aux fichiers, on peut quasiment tout faire.

Cependant, certaines opérations sont courantes et peuvent être un peu délicates à réaliser correctement. Pourquoi réinventer la roue à chaque programme ? Lorsqu'une opération est très courante, il existe souvent un module qui permet de faire ces opérations de manière standard et optimisée. Construire un programme se fait souvent en utilisant plusieurs modules un peu comme on utilise les briques de lego.

Il y a un module pour l'accès aux fichiers CSV.

Dès janvier 2003, la PEP 305 propose d'intégrer au langage Python un module pour parcourir les fichiers CSV en lecture et en écriture.

Base du module CSV

Lecture du fichier

La lecture d'un fichier CSV va être très simple.

Tout d'abord, il faut importer le module csv

import csv

Ensuite, nous allons ouvrir le fichier CSV. Notons qu'il faut obligatoirement rajouter une options à l'ouverture du fichier : l'option newline='' qui à la lecture supprime le caractère de fin de ligne. Le mieux est aussi de faire l'ouverture avec with

On va ensuite créer un reader. Cet objet reader va pouvoir être parcouru par une boucle for et à chaque passage il va transmettre le contenu de la ligne comme une simple liste. Pour la création, il y a plusieurs paramètres nommés qui sont importants :

  • delimiter qui indique le délimiteur du fichier CSV. Dans nos fichiers, c'est le point-virgule par exemple. C'est la virgule par défaut si non spécifié
  • quotechar caractère qui délimite les chaines de caractère. C'est le guillemet double par défaut.

Voici un exemple d'ouverture d'un fichier et de parcours des lignes pour un simple affichage.

with open('contacts.csv', newline='') as csvfile:
    lecteur = csv.reader(csvfile, delimiter=';', quotechar='"')
    for ligne in lecteur:
        print(ligne)

Écriture du fichier

Pour l'écriture, le principe est le même. Il faut ouvrir le fichier, et créer un objet writer qui sera chargé d'écrire dans le fichier. Chaque appel à la fonction writerow écrira une ligne.

import csv
with open('contacts.csv','w',newline='') as csvfile:
    ecrivain = csv.writer(csvfile, delimiter=';',quotechar='"')
    ecrivain.writerow(['ALbert','Enstein','USA'])

Vous pouvez essayer ci dessous un exemple complet qui va créer le fichier csv, écrire, le lire, le rouvrir en ajout, écrire un autre contact puis le relire. Vous pouvez essayer le code et charger le fichier CSV pour vérifier son contenu.

Exemple complet
import csv

with open('contacts.csv','w',newline='') as csvfile:
    ecrivain = csv.writer(csvfile, delimiter=';',quotechar='"')
    ecrivain.writerow(['Albert','Enstein','USA'])
print("fichier enregistré")

print("Lecture du fichier\n--")
with open('contacts.csv', newline='') as csvfile:
    lecteur = csv.reader(csvfile, delimiter=';', quotechar='"')
    for ligne in lecteur:
        print(ligne)
print("--")

print("Modification du fichier")
with open('contacts.csv','a',newline='') as csvfile:
    ecrivain = csv.writer(csvfile, delimiter=';',quotechar='"')
    ecrivain.writerow(['Marie','Curie','France'])

print("Fichier modifié")

print("Lecture du fichier\n--")
with open('contacts.csv', newline='') as csvfile:
    lecteur = csv.reader(csvfile, delimiter=';', quotechar='"')
    for ligne in lecteur:
        print(ligne)
print("--")

Les dictionnaires ?

Si vous ouvrez le fichier CSV que nous avons généré, vous noterez qu'il ne contient pas la première ligne qui inque que l'on a le prénom, le nom et le pays de résidence. On pourrait la rajouter en la traitant comme les autres données.

Par ailleurs, nous avons perdu le bénéfice des dictionnaires pour nos contacts, qui permettait d'avoir des données facilement accessible. Là, les éléments que nous renvoie les objets reader sont des tableaux, avec des indices donc.

Bien entendu, c'est prévu dans le module csv ! Il peut parfaitement gérer les données stockées sous forme de dictionnaire, pour les enregistrer comme pour les lire dans les fichiers CSV, en se basant sur la première ligne du CSV

Écrire à partir de dictionnaires

Au lieu de l'objet writer nous allons utiliser un obkjet DictWriter. Celui ci nous permettra d'enregistrer des données qui sont fournies sous forme de dictionnaire. Il faut juste fournir l'information du format à l'objet DictWriter, à partir d'une liste des champs qui est l'équivalent de la première ligne de CSV et qui est passé au paramètre fieldnames.

Si on ouvre le fichier en mode écrasement (w), il faut penser par commencer à écrire l'entête. Cela se fait grâce à la méthode writeheader de l'objet DictWriter. Bien entendu, si vous ouvrez en mode ajout ('a'), il ne faut pas écrire la ligne d'entête.

import csv
    with open('contacts.csv','w',newline='') as csvfile:
        champs = ['Prénom','Nom','Résidence']
        ecrivain = csv.DictWriter(csvfile, fieldnames='champs',delimiter=';',quotechar='"')
        ecrivain.writeheader()
        ecrivain.writerow({'Prénom':'ALbert','Nom':'Enstein','Résidence':'USA'})

Au lieu de l'objet reader on utilise un objet DictReader qui va :

  • lire la première ligne pour trouver les noms des colonnes
  • renvoyer chaque ligne qui suivra comme un dictionnaire et non comme un tableau

Pour la lecture, le paramétre fieldnames est optionnel. S'il n'est pas donné, le module csv utilisera la première ligne pour trouver les champs.

import csv
    with open('contacts.csv','r',newline='') as csvfile:
        lecteur = csv.DictReader(csvfile,delimiter=';',quotechar='"')
        for ligne in lecteur:
            print(ligne)
Exemple complet
import csv

champs=['Prénom','Nom','Résidence']

Scientifiques = []

albert = {'Nom':'Einstein',
    'Prénom':'Albert',
    'Résidence':'USA'
}

marie = {'Prénom':'Marie',
    'Nom':'Curie',
    'Résidence':'France'
}


with open('contacts.csv','w',newline='') as csvfile:
    ecrivain = csv.DictWriter(csvfile,fieldnames=champs, delimiter=';',quotechar='"')
    ecrivain.writeheader()
    ecrivain.writerow(albert)
print("fichier enregistré")

print("Lecture du fichier\n--")
with open('contacts.csv', newline='') as csvfile:
    lecteur = csv.DictReader(csvfile, delimiter=';', quotechar='"')
    for ligne in lecteur:
        print("-")
        for k,v in ligne.items() :
            print(f"{k} : {v}")
print("--")

print("Modification du fichier")
with open('contacts.csv','a',newline='') as csvfile:
    ecrivain = csv.DictWriter(csvfile,fieldnames=champs, delimiter=';',quotechar='"')
    ecrivain.writerow(marie)

print("Fichier modifié")

print("Lecture du fichier\n--")
with open('contacts.csv', newline='') as csvfile:
    lecteur = csv.DictReader(csvfile, delimiter=';', quotechar='"')
    for ligne in lecteur:
        print("-")
        for k,v in ligne.items() :
            print(f"{k} : {v}")
print("--")

Simplification de l'application d'annuaire de contacts

Reprenez votre code complet en remplaçant les opérations de lecture et d'écriture dans le fichier CSV par celle proposées ici en utilisant la bibliothèque CSV.