Les fichiers
Les fichiers sont une abstraction fondamentale en informatique. Ils permettent de stocker des données de manière persistante, de les partager entre programmes, et d’interagir avec le système de fichiers. Comprendre les fichiers est essentiel pour tout programmeur, car ils sont omniprésents dans la plupart des applications.
En première approche, un fichier est simplement une séquence persistante d’informations identifiée par un nom. Les idées importantes ici sont :
les données survivent à l’arrêt du programme (persistance) ;
les données sont stockées quelque part (disque, SSD, cloud, clé USB, etc.) de façon transparente pour le programme ;
on y accède à travers un identifiant (nom, chemin, URL).
Ainsi, un fichier texte, une base de données, un objet dans un stockage cloud, une réponse HTTP, ou un flux Kafka sont vus comme des variantes d’une même idée : une source de données persistantes manipulée par des opérations de lecture et d’écriture.
Les opérations abstraites
Un programme interagit avec un fichier par quelques opérations universelles.
Opération |
Signification |
|---|---|
ouvrir |
obtenir l’accès au contenu |
lire |
récupérer des données |
écrire |
ajouter/modifier des données |
position |
récupérer la position courante |
se déplacer |
changer la position de lecture/écriture |
fermer |
libérer l’accès |
On peut considérer qu”un fichier est une source ou une destination de flux de données. et que le programme possède à tout moment un curseur qui pointe sur la position courante:
A B C D E F G
^
curseur
Lors d’une lecture le curseur avance et que l’opération lire un caractère retourne le caractère lu et déplace le curseur:
A B C D E F G
^
Cette idée est commune à tous les langages de programmation et à tous les types de fichiers (texte, binaire, etc.). Elle permet de modéliser des opérations plus complexes comme :
lire une ligne (jusqu’à un saut de ligne) ;
lire un bloc de données (par exemple 1024 octets) ;
lire jusqu’à la fin du fichier ;
etc.
Un fichier est une séquence persistante de données identifiée par un nom.
Le programme possède à tout moment un qui pointe sur la position courante du fichier.
Les données dans un fichier survivent à l’arrêt du programme.
L’opération modifie le contenu du fichier
Les deux opérations principales sur un fichier sont
Les opérations abstraites sur fichiers sont différentes selon le type de fichier (texte vs binaire).
Les fichiers en langage C
En langage C, les fichiers sont manipulés à travers un ensemble de fonctions standard définies dans la bibliothèque stdio.h. Les fichiers sont représentés par des pointeurs de type FILE*, et les opérations de lecture et d’écriture sont effectuées à l’aide de fonctions telles que fopen, fread, fwrite, fclose, etc.
Par exemple, le code suivant ouvre un fichier texte en lecture, lit son contenu et l’affiche à l’écran.
#include <stdio.h>
int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
perror("Erreur lors de l'ouverture du fichier");
return 1;
}
char buffer[256];
while (fgets(buffer, sizeof(buffer), file) != NULL) {
printf("%s", buffer);
}
fclose(file);
return 0;
}
Les fonctions de manipulation de fichiers en C sont définies dans la bibliothèque
Les fichiers en C sont représentés par des pointeurs de type
ouvre un fichier en langage C
La fonction
fopenretourne un pointeur de typeFILE*.Les fonctions permettent de lire et d’écrire des données binaires.
La fonction
fclosepermet de libérer les ressources associées à un fichier.
Les fichiers en Python
Une vidéo de présentation des fichiers…
Python peut traiter des fichiers texte et des fichiers binaires (images, sons, etc…). Pour ce cours, nous travaillerons exclusivement avec des fichiers contenant du texte. Nous utiliserons à titre d’exemple l’oeuvre de Corneille, Le Cid, contenue dans le fichier lecid.txt.
Ouverture du fichier
Ouvrir un fichier c’est établir la connexion avec la ressource contenant les données. On ouvre un fichier avec la fonction open() qui peut ne nécessiter qu’un seul argument, le nom du fichier à ouvrir. Si aucune arborescence n’est précisée, le répertoire dans lequel le fichier est recherché est celui depuis lequel a été lancé l’interpréteur Python.
>>> f = open('lecid.txt')
>>> f
<_io.TextIOWrapper name='index.rst' mode='r' encoding='cp1252'>
Le mode d’ouverture par défaut du fichier est en lecture seule : mode='r' et l’encodage est celui du terminal depuis lequel a été lancé l’interpréteur Python : encoding='cp1252'. Ce sera cependant une bonne pratique que de préciser explicitement ces deux paramètres.
open() retourne un file-object de type io.TextIOWrapper. Cette classe hérite de io.TextIOBase et io.IOBase.
>>> type(f)
<class '_io.TextIOWrapper'>
>>> import io
>>> isinstance(f, io.TextIOBase)
True
>>> isinstance(f, io.IOBase)
True
L’objet retourné par open() dispose de plusieurs méthodes. Ici seules les plus importantes ont été conservées pour l’affichage. L’encodage utilisé est également disponible dans un attribut.
>>> dir(f)
[..., 'close', ..., 'read', ..., 'readline', 'readlines', ..., 'write', 'writelines']
>>> f.encoding # interpréteur Python lancé depuis une console Windows
'cp1252'
Comme précisé plus haut, c’est cependant une bonne pratique de préciser explicitement l’encodage du fichier dans les paramètres de la fonction open(). C’est même indispensable lorsque le fichier comporte des caractères accentués. Le nom du fichier est accessible dans l’attribut name:
.. code-block:: python
>>> f = open('lecid.txt', mode='r', encoding='utf8')
>>> f.encoding
'utf8'
>>> f.name
'lecid.txt'
Fermeture du fichier
Fermer un fichier c’est rompre la connexion avec la ressource contenant les données, et donc libérer cette dernière pour le système d’exploitation.
La fonction close() permet de fermer le fichier une fois la lecture effectuée.
>>> f.closed
False
>>> f.close()
>>> f.closed
True
La bonne pratique de manipulation d’un fichier consiste donc en 3 étapes :
ouvrir le fichier
réaliser les opérations de lecture/écriture
fermer le fichier
La construction with
L’action d’ouverture-fermeture d’un fichier est non seulement très courante mais la fermeture du fichier, après les opérations de lecture/écriture, nécessaire. C’est une façon concise, efficace et élégante de fermer le fichier après les opérations de lecture/écriture.
>>> with open('lecid.txt', mode='r', encoding='utf8') as f:
... s = f.read()
...
>>> f.closed
True
Cette méthode est sure car le fichier est automatiquement fermé après l’exécution des instructions du bloc with.
with est un context manager. Il permet de définir des opérations à exécuter :
avant les instructions du bloc ;
après les instructions du bloc.
Note
with est utilisé ici avec un objet de type io.TextIOWrapper mais peut être employé avec tout objet implémentant les méthodes :
__enter__();et
__exit__().
Lecture du contenu
Il existe plusieurs façon de lire le contenu d’un fichier:
On peut récupérer l’intégralité du contenu dans une chaîne de caractères avec la méthode read() comme dans l’exemple ci dessus.
>>> s = f.read()
>>> type(s)
<class 'str'>
>>> len(s) # nombre de caractères
95302
>>> s[-46:]
'Laisse faire le temps, ta vaillance et ton roi'
Un autre appel à read() retourne la chaîne vide (car tout le fichier a été lu par l’instruction précédente).
>>> s = f.read()
>>> s
''
On peut aussi récupérer l’intégralité du contenu dans une liste de chaînes de caractères avec readlines().
>>> with open('lecid.txt', mode='r', encoding='utf8') as f:
... l = f.readlines()
>>> type(l)
<class 'list'>
>>> len(l) # nombre de lignes
3236
>>> l[-1]
'Laisse faire le temps, ta vaillance et ton roi'
>>> for i in l[785:787]:
... print(i, end='')
...
Je suis jeune, il est vrai ; mais aux âmes bien nées
La valeur n'attend point le nombre des années.
On peut également lire le fichier ligne par ligne avec readline().
>>> f.readline()
'LE CID\n'
>>> f.readline()
'======\n'
>>> f.readline()
'\n'
readline() n’a d’intérêt qu’encapsulé dans une boucle for ou while simple et que si la taille du fichier est trop importante pour un chargement total en mémoire. Sinon readlines() sera préférée.
>>> with open('lecid.txt', mode='r', encoding='utf8') as f:
... for i in range(10):
... print(f.readline())
Ecriture dans un fichier
On écrit dans un fichier avec la méthode write(). Il faut auparavant ouvrir le fichier en écriture (mode='w').
>>> with open('file.txt', mode='w', encoding='utf8') as f:
... f.write("M. Churchill, si j'étais votre femme, je mettrais du poison dans votre café !\n")
... f.write("Lady Astor, si j'étais votre mari, je le boirais !")
...
78
50
La méthode write() retourne le nombre de caractères écrits dans le fichier. On peut également utiliser la méthode writelines() qui permet d’écrire dans un fichier un ensemble de chaines de caractères stockées dans une liste.
Les fichiers csv
Le format csv Comma Separated Value est couramment utilisé pour échanger des données au format texte. Le module csv de Python dispose de méthodes spécifiques pour lire ce genre de format.
On considère le fichier des observations météo de la station d’Edimbourg en Ecosse Edinburgh_2015_Oct.csv. Ouvrir ce fichier avec un éditeur de texte pour en observer la structure. Pour en lire le contenu, Python utilise la fonction reader() qui retourne un itérable.
>>> with open('Edinburgh_2015_Oct.csv', 'r') as f:
... r = csv.reader(f)
... l = list(r) # l'itérable est converti en liste
...
Le format Comma Separated Value ne fixe pas le délimiteur utilisé pour séparer les données. Pour le format anglo-saxon, la virgule , est utilisée. La taille de la liste construite à partir de l’objet retourné par reader() est égale au nombre de lignes du fichier. La première ligne contient l’en tête. A partir de la seconde, on trouve les données.
>>> r.dialect.delimiter
','
>>> len(l)
44703
>>> l[0]
['date-time', 'atmospheric pressure (mBar)', 'rainfall (mm)', 'wind speed (m/s)', 'wind direction (degrees)', 'surface temperature (C)', 'relative humidity (%)', 'solar flux (Kw/m2)', 'battery (V)']
>>> l[1] # la première ligne de données
['2015/10/01 00:01', '1035', '0', '0', '0', '9.28', '93.9', '0', '13.77']
A expérimenter…
On considère le fichier synop.2015110112.csv qui contient des données produites par Météo France au format csv.
Ouvrir ce fichier avec un éditeur de texte pour en observer la structure.
Le séparateur décimal français étant la virgule ,, cette dernière ne peut pas être utilisée comme délimiteur. La convention française est d’utiliser le point virgule ;. Il faut pour cela utiliser le paramètre delimiter de la fonction reader().
>>> with open('synop.2015110112.csv', 'r') as f:
... r = csv.reader(f, delimiter=';')
... l = list(r)
Combien de lignes comporte le fichier ? Combien y a t-il de données par ligne ?
Note
Le travail avec les fichiers csv est facilité dans Visual Studio Code par l’extension Rainbow CSV. Elle s’installe à partir du menu Affichage > Extensions.
Ce qu’il faut retenir
est la fonction qui permet d’ouvrir un fichier
est la fonction qui permet de fermer un fichier
La fermeture de fichier est automatique si on utilise la construction
On peut ouvrir un fichier en ne précisant que son nom
Si on ne le précise pas le mode d’ouverture par défaut d’un fichier est en écriture
Lorsqu’on ouvre un fichier, c’est une bonne pratique de préciser son mode d’ouverture, lecture ou écriture
Si on ne le précise pas l’encodage par défaut lors de l’ouverture d’un fichier est celui du système d’exploitation
Lorsqu’on ouvre un fichier, c’est une bonne pratique de préciser son encodage
sont les 3 méthodes de lecture d’un fichier texte
La méthode
read()retourne une chaine de caractèresLa méthode
readlines()retourne une liste de chaine de caractèressont les 2 méthodes d’écriture dans un fichier texte
On peut itérer sur l’objet retourné par la fonction
open()Un fichier
csvest un fichier texteUn fichier
csvne peut être lu qu’avec le modulecsvLe module
csvfacilite la lecture d’un fichiercsvLa première ligne d’un fichier
csvcomporte des donnéesLe délimiteur d’un fichier
csvest toujours le caractère,Le délimiteur d’un fichier
csvest toujours le caractère;On peut préciser le délimiteur d’un fichier
csvà la lecture
Il est nécessaire que VS Code soit démarré sur la machine hôte, pointe vers le répertoire e3-programmation-labs-student et que le container Docker soit lancé.
Le répertoire concerné est lab_python_lecture_donnees. Lisez attentivement le fichier README.md pour comprendre la consigne. Il est efficace d’y accéder depuis le dépôt distant pour profiter du formatage.
Une fois l’exercice terminé, effectuer une revue de code, ajouter la documentation, et s’assurer que les repos local et distant soient correctement synchronisés.