Accueil
Mes tutoriels sur la programmation

Tutoriel Python - sommaire


Vous pouvez me contacter via Facebook (questions, critiques constructives) : page Facebook relative à mon site

Les fichiers de données en Python

En mode commande ou en mode programmé, on peut manipuler des fichiers de données (extension .txt).
Mais pourquoi utiliser des fichiers de données dans le cadre de programmes Python ?
Dès que vous fermez un programme les données contenues dans les variables ne sont pas sauvegardées.
Imaginez un jeu, il faut récupérer les scores des parties précédentes pour savoir si le joueur progresse ou pas. Il faut donc sauvegarder chaque score dans un fichier de données (et non pas dans des variables).
Le plus souvent on dit tout simplement "fichiers" pour désigner les fichiers de données.

les fichiers .txt sont des "fichiers texte" contenant une suite de caractères au format ASCII.
Ces fichiers peuvent être créés par l'application "bloc-notes" ou par un éditeur de textes tel "Notepad" ou par l'IDLE.

Contenu provisoire du fichier "taxons.txt" :

éponges
Cnidaires
Cténaires
Vers
Crustacés
Echinodernes
Bryozaires
Urocordés
Poissons osseux
Poissons cartilagineux
Gastéropodes
Bivalves
Ceéphalopodes
Cirripèdes
Décapodes
Cétacés
Pinnipèdes
échinodermes
Anémones
Amphipodes
Méduses
Coraux

Contenu provisoire du fichier de données "especes.txt" :

Seiche
Calmar
Moule commune
Huitre creuse
Huitre plate
Balane
Crevette grise
Bouquet
Sole
Bar
Crabe vert
étrille
Tourteau
Arénicole
Roussette
Hareng
Merlan
Roussette
Hareng
Merlan

Remarque : dans les deux fichiers, une donnée par ligne.

Ces deux fichiers ont été produits avec l'éditeur Notepad et encodés en ANSI.
Ainsi les lettres accentuées sont affichées proprement.

Manipuler les fichiers de données avec l'interpréteur

Première batterie de commandes

>>> import os
>>> os.getcwd()
'C:\\Python39'

Il faut activer le module "os" afin de gérer les répertoires.
Dès que vous êtes sous l'interpréteur le répertoire par défaut est celui qui contient l'exécutable de l'interpréteur : c:\Python39
La commande os.getcwd() précise le répertoire courant.
Or mes programmes et mes fichiers de données sont dans le dossier c:\python_prog.
Il faut donc changer de "directory".

>>> os.chdir("c:/python_prog")
>>> fichier = open("especes.txt", "r")
>>> fichier.readlines()
['seiche\n', 'calmar\n', 'pouple\n', 'moule commune\n', 'huitre creuse\n', 'huitre plate\n', 'balane\n',
 'crevette grise\n', 'bouquet\n', '\n']
>>>fichier.close()
>>> fichier = open("taxons.txt","r")
>>> fichier.readlines()
['éponges\n', 'cnidaires\n', 'cténaires\n', 'vers\n', 'mollusques\n', 'crustacés\n', 'échinodernes\n', 
'bryozaires\n', 'urocordés\n', 'poissons osseux\n', 'poissons cartilagineux\n']
>>>fichier.close()
>>> fichier =open('especes.txt','r')
>>> print(fichier.readline())
seiche
>>> print(fichier.readline())
calmar
>>>fichier.close()

os.chdir("c:/python_prog") : accès au répertoire qui contient mes programmes et fichiers.
Pour lire le contenu d'un fichier il faut l'ouvrir en lecture seule. Donc dans la fonction open() le deuxième argument doit être "r" (comme 'read').
La méthode readlines() (avec un 's') appliquée à l'objet 'file' permet de lire tout le fichier et retourne son contenu sous forme d'une liste.
Notez que chaque élément de la liste se termine par '\n' (symbole qui commande un saut de ligne).

la méthode readline() (sans 's') permet de lire la ligne courante. Après l'ouverture d'un fichier, la ligne courante est la première.
La méthode provoque aussi le déplacement du pointeur vers la ligne suivante ou EOF (End Of File).

Deuxième batterie de commandes

>>> import os
>>> os.getcwd()
'C:\Python39'
>>> os.chdir("c:/python_prog")
>>> fichier = open("especes.txt","a")
>>> fichier.write("\n sole")
>>> fichier.write("\n bar")
>>> fichier.readlines()
...
io.UnsupportedOperation: not readable
>>> fichier.close()

Pour pouvoir ajouter du contenu à un fichier il faut l'ouvrir en mode ajout (deuxième argument :"a").
Pour ajouter une ligne, il faut utiliser la méthode write() à l'objet de type 'file'.
La chaine ajoutée, doit contenir "\n" pour créer un saut de ligne.

Vous voyez aussi que j'ai tenté de lire un fichier ouvert en ajout ; tentative qui s'est soldé par un message d'erreur.
N'oubliez pas de fermer le fichier avec la méthode close().

Manipuler les fichiers de données dans le cadre de programmes

Un conseil : le programme (fichier d'extension .py) et le fichier de données traité par ce programme, doivent être de préférence dans le même répertoire. Ainsi le problème parfois délicat, du chemin relatif sera résolu ...

Un programme qui gère un fichier associé à un jeu

Le programme lit un fichier qui contient le dernier score.
Le jeu se déroule et le score de la session est produit.
Le fichier est de nouveau ouvert pour enregistrez le nouveau score ; le contenu précédent est écrasé !

Exemple de contenu du fichier (score.txt) :

pseudo, date et score : covid62 14:49:22:01:2021 score =  55

Le code

#nom du fichier : structure_jeu.py
import random
import datetime as dh

fichier =open("score.txt","r")
contenu = fichier.read()
print(f"ancien score : {contenu}")
fichier.close()

score_session = 0
pseudo = input ("tapez votre pseudo : " )
for i in range(10):
     """ici il y aurait appel de la fonction
	correspondant à une partie
     """
	score_partie = random.randint(1,11)
score_session +=score_partie

# conservation du scrore de la dernière session 
print(f"votre nouveau score : {score_session} ")
cejour = dh.datetime.today()
datecourante = cejour.strftime("%H:%M:%d:%m:%Y")
contenu = " pseudo, date et score : " + pseudo + " " + datecourante + " score =  " + str(score_session)
fichier =  open("score.txt", "w")
fichier.write(contenu)
fichier.close()

Attention le code correspondant au jeu proprement dit ne figure pas.
Donc je suis obligé de générer de façon aléatoire le score de chaque partie.
Une session c'est 10 jeux, d'où la boucle.

Programme pour lire séquentiellement un fichier

Le programme ci-dessous ouvre en lecture "especes.txt" OU "taxons.txt".

#nom programme : ouvrir_en_lecture.py
#objet : ouvrir le fichier de données 'especes' ou 'taxons' en lecture

nom_fichier =input("tapez 'especes.txt' ou 'taxons.txt' : ")

with open(nom_fichier, "r") as fichier: 
    ligne = fichier.readline()      # lire première ligne du fichier
    while ligne != "":
        print(ligne)
        ligne = fichier.readline() #lire ligne suivante
fichier.close()

Notez la syntaxe pour ouvrir le fichier : with open(nom_fichier, "r") as fichier
Cette instruction permet d'ouvrir et de fermer un fichier de manière efficace. En effet, si pour une raison ou une autre, l'ouverture ou la lecture du fichier conduit à une erreur, l'utilisation de la syntaxe "width … open … as … garantit une fermeture effective du fichier.

La méthode realine() appliquée à l'objet 'file' permet de lire une ligne dans le fichier.
readline() veut dire "lire la ligne pointée". Après ouverture d'un fichier, la ligne "pointée" est la première.

La commande de fermeture doit être au niveau d'indentation que la commande d'ouverture.
Trace de l'exécution (extrait) :

 
Tapez 'especes.txt' ou 'taxons.txt' : especes.txt
seiche
calmar
pouple
moule commune
huitre creuse
huitre plate
balane
crevette grise
...

Programme pour ajouter des données à l'un des deux fichiers

Il faut pouvoir mettre à jour les fichiers de données et en particulier y ajouter des données.

Le programme ci-dessous permet d'ajouter des lignes au fichier "especes.txt" OU "taxons.txt".

#nom programme : ouvrir_en_ajout.py
# objet : ouvrir en ajout especes.txt OU taxons.txt

nom_fichier = input("tapez 'especes.txt' ou 'taxons.txt' : " )
reponse ="o"
with open(nom_fichier, "a") as fichier:
    while reponse  in "oO":
        ajout =input ("saisir une espèce ou un taxon : ")
        ajout = "\n" + ajout
        fichier.write(ajout)
        reponse =input( "Encore des ajouts O/N ? : " )
fichier.close()

Pour ajouter des données, en fin de fichier, il faut l'ouvrir en mode "a" (comme "append").
Pour créer une nouvelle ligne dans le fichier de données il faut utiliser la méthode write() à l'objet de type 'file'.

Programme pour faire une recherche aléatoire dans l'un des deux fichiers

Le programme ci-dessous permet d'ouvrir en lecture "especes.txt" OU "taxons.txt".

Le code :

#nom programme : ouvrir_aleatoire.py
# objet : recherche aléatoire dans un fichier
import random
nom_fichier =input("Tapez 'especes.txt' ou 'taxons.txt' : ")
reponse ="o"
with open(nom_fichier, "r") as fichier: 
   liste = fichier.readlines()
reponse = "o"
while reponse in "oO":
    element =random.choice(liste)
    print (element)
    reponse =input("Encore un tirage au sort  O/N ? " )
fichier.close()

Le fichier choisi est ouvert en lecture seule.
La méthode readlines() retourne tout le contenu du fichier sous forme d'une liste.
Grâce à la fonction choice() du module random on tire au sort l'un des éléments de la liste.
Trace d'exécution :

Tapez 'especes.txt' ou 'taxons.txt' : taxons.txt éponges Encore un tirage au sort O/N ? o poissons osseux Encore un tirage au sort O/N ? o bryozaires Encore un tirage au sort O/N ? o gastéropodes Encore un tirage au sort O/N ? o mollusques Encore un tirage au sort O/N ? n

Ouvrir un fichier en lecture - écriture

Jusqu'à présent je sais ouvrir un fichier en écriture (modes "w" ou "a") et alors je ne peux pas lire le contenu OU je l'ouvre en lecture (mode "r") et alors je ne peux pas écrire dédans ...
Je peux bien sûr, dans le même programme, enchainer plusieurs ouvertures avec un mode différent. Mais il y a plus simple : le deuxième paramètre de la méthode open() peut être égal à "r+" qui autorise la lecture et l'écriture.

Ci-dessous programme qui permet d'ouvrir "especes.txt" OU "taxons.txt".
Le contenu actuel du fichier est d'abord affiché, ainsi l'utilisateur a un "pense-bête". Puis il peut ajouter des lignes au fichier

Première version

Le programme ci-dessous ouvre en lecture/écriture "especes.txt" OU "taxons.txt".

Le code

#nom programme : ouvrir_en_lecture_ecriture.py
# objet : ouvrir le fichier de données 'especes' ou 'taxons' en lecture /ecriture
nom_fichier =input("tapez 'especes.txt' OU 'taxons.txt' : ")
with open(nom_fichier, "r+") as fichier:
       contenu = fichier.readlines()
       print(type(contenu))
       #contenu est de type 'list'		# instruction provisoire
       print("contenu actuel du fichier: ")
       print(contenu)
       reponse ="o"
       print()
       reponse =input("Voulez vous ajouter une espèce / un taxon o/n ? ")
       while reponse  in "oO":
                ajout =input ("Nom de l'espèce / du taxon : ")
                ajout = "\n" + ajout
                fichier.write(ajout)
                reponse =input( "Encore un ajout o/n  ? : " )
fichier.close()

Trace d'exécution du programme

Tapez 'especes.txt' OU 'taxons.txt' : especes.txt <class 'list'> contenu actuel du fichier: ['calmar\n', 'patelle\n', 'Pouple\n', 'Moule commune\n', 'Huitre creuse\n', 'Huitre plate\n', 'Balane\n', 'Crevette grise\n', 'Bouquet\n', 'Sole\n', 'Bar\n', 'Crabe vert\n', 'Étrille\n', 'Tourteau\n', 'Arénicole\n', '\n', 'morue'] Voulez vous ajouter une espèce / un taxon o/n ? o Nom de l'espèce / du taxon : plie Encore un ajout o/n ? : n

Analyse du code

with open(nom_fichier, "r+") as fichier : le deuxième argument de la méthode open est "r+"

Critiques du code

Ce programme est souple : on peut lire tout le contenu d'un fichier et ensuite, si on le souhaite, on peut écrire dans ce fichier.
Problème : le contenu du fichier est difficile à lire à cause de symboles 'parasites' : guillemets internes, virgules internes, retour chariot. Il faudrait pouvoir supprimer ces symboles ...

Version améliorée

La méthode readlines() retourne une liste. Il faudrait pouvoir convertir cette liste en chaine. Nous avions vu dans le chapitre 8 que c'est possible grâce à la méthode join() appliquée à la liste.

Extrait du code de la nouvelle version

...
       contenu = fichier.readlines()
       contenu =" ; ".join(contenu)
       contenu =contenu.replace("\n", " ")
       print("contenu actuel du fichier: ")
...

La liste "contenu" est convertie en chaine grâce à la méthode join(). Dans cette chaine les mots sont séparés par des " ;".
Puis on remplace les symboles "\n" -c'est à dire les retours chariot - par des espaces : emploi de la méthode replace().

La trace d'exécution

Tapez 'especes.txt' ou 'taxons.txt' : taxons.txt Contenu actuel du fichier: Éponges ; Cnidaires ; Cténaires ; Vers ; Crustacés ; Échinodermes ; Bryozoaires ; Urocordés ; Poissons osseux ; Poissons cartilagineux ; Gastéropodes ; Bivalves ; Céphalopodes ; Cirripèdes ; Décapodes ; Cétacés ; Pinnipèdes ; échinodermes ; Anémones ; Amphipodes ; Méduses Voulez vous ajouter une espèce / un taxon o/n ? o Nom de l'espèce / du taxon : coraux Encore un ajout o/n ? : n

Reconnaissez que l'affichage du contenu est beaucoup plus limpide.

La méthode writelines()

La méthode writelines() permet d'ajouter d'ajouter d'un coup plusieurs lignes à un fichier.

Exemple de programme basé sur cette méthode

# nom du programme : writelines.py
# ajout de plusieurs lignes à un fichier txt
with open ("especes.txt", "r+") as fichier:
        ligne = fichier.readline()      # lire première ligne du fichier
        print("contenu initial : ")
        while ligne != "":
                print(ligne, end =" ")
                ligne = fichier.readline() #lire ligne suivante

        # ajouts
        donnees = ["Roussette\n","Hareng\n","Merlan\n"]
        fichier.writelines(donnees)
  
        fichier.seek(0)
        print("nouveau contenu :")
        ligne = fichier.readline()      # lire première ligne du fichier
        while ligne != "":
                print(ligne, end =" ")
                ligne = fichier.readline() #lire ligne suivante
fichier.close()

Analyse du code

Le fichier "especes.txt" est ouvert en mode "r+" : lecture et écritue.
On lit séquentiellement le fichier avec une boucle basée sur readline() pour afficher le contenu inital du fichier.

La variable "données" contient une liste de trois éléments, il pourrait y en avoir 30 ...
Grâce à une commande basée sur la méthode writelines(liste) le contenu de cette liste est ajouté au fichier sous forme de 3 lignes.

fichier.seek(0) : suite aux ajouts le pointeur est en EOF (End Of File) ; grâce à l'instruction "seek(0)" le pointeur sélectionne de nouveau la première ligne.
Pour terminer, on lit de nouveau séquentiellement le fichier, donc on affiche le nouveau contenu.