Accueil

Traduction

Tutoriel Python - sommaire

Tutoriel Python - recherche

L'auteur : Patrick Darcheville

Vous pouvez me contacter via Facebook pour questions & suggestions : Page Facebook relative à mon site

Python et les fichiers texte (.txt)

Dès que vous fermez un programme les données produites sont perdues.
Pour stocker de façon permanente des données on pense aux bases de données. Mais pour de nombreuses applications, utiliser une BD alors qu'il n'y a que quelques données à stocker, c'est "tuer une mouche avec un canon".

Les fichiers texte

Dans ce chapitre je n'évoque que le traitement en Python des fichiers TXT.
Pour le traitement des fichiers CSV & JSON via la bibliothèque pandas : Chapitre 16

Mais revenons aux fichiers TXT (données non formatées).

Ces fichiers sont enregistrés dans le dossier c:/python_prog ; donc dans le même dossier que les scripts Python.

Contenu du fichier "taxons.txt"

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

Notez qu'il n'y aucun formatage des données, uniquement des sauts de ligne.
Encodage en ANSI afin que les lettres accentuées soient affichées proprement.

Contenu du fichier "especes.txt"

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

Manipuler les fichiers TXT en mode interactif

Avant de passer à la programmation nous allons manipuler ces fichiers via la console Python. Vous verrez qu'on peut déjà faire pas mal de choses ...

Accéder au bon dossier

>>> import os
>>> os.getcwd()
'C:\\Users\\darch'
>>> os.chdir("c:\\Users\\darch")

J'ai importé le module os ( OS comme Operating System).
Ce module propose des méthodes qui permettent de manipuler fichiers et dossiers.
La fonction os.getcwd() précise le répertoire courant. Notez qu'il s'agit du dossier C:\Python39
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:\\Users\\darch'.

Ouvrir et lire le fichier "especes.txt"

Mes fichiers texte sont dans un autre dossier ; ils sont dans : c:\python_prog. Il faut donc changer de "directory" (répertoire).

>>> 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()

Cet affichage du contenu du fichier n'est pas très satisfaisant.

Ouvrir et lire le fichier "taxons.txt"

On suppose bien sûr qu'on est toujours dans le bon répertoire.

 >>> with open('taxons.txt','r') as fichier :
...     fichier.readlines()
...
['éponges\n', 'Cnidaires\n', 'Cténaires\n', 'Vers\n', 'Crustacés\n', 
'Echinodernes\n', 'Bryozaires\n', 'Urocordés\n', 'Poissons osseux\n',
 'Poissons cartilagineux\n', 'Gastéropodes\n', 'Bivalves\n', 
 'Céphalopodes\n', 'Cirripèdes\n',
 'Décapodes\n', 'Cétacés\n', 'Pinnipèdes\n', 'échinodermes\n',
 'Anémones\n', 'Amphipodes\n', 'Méduses\n', 'Coraux\n']
>>>

Notez la nouvelle syntaxe pour ouvrir le fichier : with open(nom_fichier, "r") as fichier :
Cette commande permet d'ouvrir et de fermer un fichier de manière efficace. En effet, si pour diverses raisons, l'ouverture ou la lecture du fichier conduit à une erreur, l'utilisation de la syntaxe "with open ... as objectFile" garantit une fermeture effective du fichier.
L'instruction "with open ..." crée un bloc d'instructions. Les commandes de manipulation du fichier doivent être dans ce bloc.
À la sortie du bloc il y a fermeture automatique du fichier.

Lire un fichier avec la méthode read()

>>> with open('especes.txt','r') as fichier :
...     contenu = fichier.read()
...
>>> print(contenu)
Seiche
Calmar
Moule commune
Huitre creuse
Huitre plate
Balane
Crevette grise
Bouquet
Sole
Bar
...

La méthode read() lit la totalité du fichier et retourne le contenu sous forme d'une chaine de caractères unique ici récupérée dans la variable "contenu".
print(contenu) : la chaine est affichée sur plusieurs lignes grâce aux (\n) à la fin de chaque ligne du fichier.
On obtient donc un affichage plus satisfaisant qu'avec readlines()

Lire un fichier avec la méthode readline()

La méthode readline() (sans s à la fin) lit seulement une ligne du fichier et la retourne sous forme d'une chaine.
Donc le premier appel de cette méthode lit la première ligne, le deuxième appel lit la seconde, etc.

>>> with open('taxons.txt','r') as fichier :
...     ligne = fichier.readline()
...     while ligne !="" :
...             print(ligne)
...             ligne =fichier.readline()
...
éponges

Cnidaires

Cténaires
...

Pour lire successivement les lignes du fichier il faut une commande "readline()" avant la boucle et une deuxième dans la boucle.
L'itération s'effectue tant que la fin de fichier n'est pas détectée.
Notez les lignes vierges ... Il y a en effet le saut de ligne de la commande print() et le saut de ligne provoqué par le caractère "\n".

Lire un fichier sans utiliser une des trois méthodes

Ces trois méthodes sont surtout utiles en mode console : elles permettent de lire un fichier (ou une ligne) sans recourir à une boucle et à la commmande print().
Sachez qu'un "objectFile" peut être parcouru par une boucle.

>>> with open('taxons.txt','r') as fichier :
...     for ligne in fichier :
...             print(ligne,end =" ")
...
 éponges
 Cnidaires
 Cténaires
 Vers
 Crustacés
 Echinodernes
 Bryozaires
 ...
 

En mode programmé on préférera cette solution.
Remarquez que cette fois les lignes vierges ont disparu gràce au deuxième argument de la commande print() qui supprime le saut de ligne par defaut de cette fonction.

Écrire dans un fichier TXT

Vous savez désormais lire le contenu d'un fichier TXT. Bien évidemment il est possible d'écrire dans ce type de fichier.

Créez avec NotePad un fichier TXT vierge de tout contenu dans le dossier "c:/python_prog" et nommez le "vierge.txt".

Ajout de texte à ce fichier

>>> os.getcwd()
'c:\\python_prog'
>>> with open('vierge.txt','a') as fichier :
...     fichier.write("sole")
...     fichier.write("bar")
...     fichier.write("morue")
...
4
3
5
>>> with open('vierge.txt','r') as fichier :
...     fichier.readlines()
...
['barsolebarmorue']
>>>

On ouvre ensuite le même fichier en lecture et on constate qu'il y a un gros problème : les textes ont bien été ajoutés mais sans saut de ligne ; ils sont collés !

Écrire avec écrasement de l'ancien contenu

Le fichier "vierge.txt" n'est plus vide mais contient des données qui ne nous satisfont pas.
Nous allons l'ouvrir en mode "w" afin que l'ajout écrase l'ancien contenu.

>>>with open('vierge.txt','w') as fichier :
...     fichier.write("sole \n")
...     fichier.write("bar \n")
...     fichier.write("morue \n")
...
6
5
7
>>>with open('vierge.txt','r') as fichier :
...     lignes = fichier.read()
>>>print(lignes)
sole
bar
morue

Cette fois le fichier contient bien 3 lignes de texte.
Si vous doutez, ouvrez ce fichier avec NotePad !

Autres méthodes applicables à un objet de type file

>>> import os
>>> os.chdir("c:/python_prog")
>>> fichier =open("especes.txt","r")
>>> fichier.read()
'Seiche\nCalmar\nMoule commune\nHuitre creuse\nHuitre plate\nBalane\nCrevette grise\n
Bouquet\nSole\nBar\nCrabe vert\nétrille\nTourteau\nArénicole\n\nRoussette\n
Hareng\nMerlan\nRoussette\nHareng\nMerlan\nRoussette\nHareng\nMerlan\n'
>>> fichier.readable()
True
>>> fichier.writable()
False
>>> fichier.tell()
229
>>> fichier.seek(1)
1
>>> fichier.tell()
1

J'ai ouvert le fichier en lecture ; aussi la méthode readable() retourne True et la méthode writable() retourne False.
La méthode tell() indique la position du curseur. Après une lecture du fichier le curseur pointe la fin de fichier.
La méthode seek() déplace le curseur.

Manipuler un fichier texte dans le cadre d'un programmes

Le programme qui manipule un fichier TXT et ce dernier doivent de préférence être 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é !

Le programme

Il lit l'ancien contenu du fichier texte puis écrit dans ce fichier le nouveau score et la date.

#nom du fichier : structure_jeu.py
# coding: utf-8
import random
import os
import datetime as dt
courant = os.getcwd()
print(f"Répertoire courant : {courant}")
with open("score.txt","r") as fichier:
        contenu = fichier.read()
print(f"Votre ancien score : {contenu}")
score_session = 0
pseudo = input ("tapez votre pseudo : " )
for i in range(10):
        """ici il y aurait appel de la fonction
         correspondant à une partie
         fonction retourant le score d'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 = dt.datetime.today()
datecourante = cejour.strftime("%H:%M:%d:%m:%Y")
contenu = " pseudo, date et score : " + pseudo + " " 
+ datecourante + " " + str(score_session)
with open("score.txt", "w") as fichier:
        fichier.write(contenu)

Attention le code correspondant à une partie est remplacée par la génération aléatoire d'un entier compris entre 1 et 10.
Une session de jeu c'est 10 parties d'où la boucle.

Le rendu

Répertoire courant : C:\python_prog
Votre ancien score :  pseudo, date et score : darche 15:34:10:08:2024 59
tapez votre pseudo : darche
votre nouveau score : 60 

À la différence du mode console, le répertoire courant en mode programme est celui qui contient le script et donc le fichier TXT.

Programme basé sur writelines()

La méthode writelines() permet d'ajouter plusieurs lignes en une seule instruction.
Voyons cette méthode au travers d'un programme.

L'utilisateur lit l'ancien contenu du fichier ; fait des ajouts puis lit le contenu actualisé par les ajouts.

Version initiale du script

# nom du programme : writelines.py
# coding: utf-8
# ajout de plusieurs lignes à un fichier txt
print("Ancien contenu : ")
with open ("especes.txt", "r") as fichier:
        ancien_contenu = fichier.read()    
        print(ancien_contenu, end =" ")
print("-----------------------------------")
with open ("especes.txt", "a") as fichier:
        ajouts = ["Roussette\n","Hareng\n","Merlan\n"]
        fichier.writelines(ajouts)

print("Nouveau contenu : ")     
with open ("especes.txt", "r") as fichier:
        nouveau_contenu = fichier.read()
        print(nouveau_contenu, end =" ")

Il faut ouvrir trois fois le même fichier texte avec à chaque fois un mode différent.
C'est un peu lourd ...

Le rendu

Ancien contenu : 
Seiche
Calmar
Moule commune
Huitre creuse
...
Tourteau
Arénicole
 -----------------------------------
Nouveau contenu : 
Seiche
Calmar
Moule commune
Huitre creuse
...
Tourteau
Arénicole
Roussette
Hareng
Merlan

On a bien rajouté trois lignes dans le fichier.

Nouvelle version du programme

Je vous propose maintenant une variante qui n'exige qu'une ouverture du fichier (et non pas trois).

# nom du programme : writelines_bis.py
# coding: utf-8
with open ("especes.txt", "r+") as fichier:
    print("Ancien contenu :")
    for ligne in fichier :
            print(ligne,end =" ")
    print("--------------------------")
    ajouts = ["Roussette\n","Hareng\n","Merlan\n"]
    fichier.writelines(ajouts)
    fichier.seek(0)   # repointer le début du ficher
    print("Nouveau contenu :")
    for ligne in fichier :
        print(ligne,end =" ")

Le rendu

Avant de lancer la nouvelle version, ouvrez le fichier "especes.txt" avec NotePad, supprimez les trois dernières lignes ajoutées via la première version ("Roussette\n","Hareng\n","Merlan\n") puis fermez le fichier. Vous pouvez alors exécuter le nouveau script.

Ancien contenu :
 Seiche
 Calmar
...
 Tourteau
 Arénicole
  --------------------------
Nouveau contenu :
 Seiche
 Calmar
 ...
 Tourteau
 Arénicole
 
 Roussette
 Hareng
 Merlan

Trois lignes ajoutées !
Vous pouvez aussi ouvrir le fichier texte avec NotePad pour constater les ajouts.

Programme pour lire un fichier caractère par caractère

Quand vous aborderez la programmation de jeux vidéos en Python vous verrez qu'il peut être utile de lire un fichier tXT qui sert de modèle pour créer le décor du jeu : afficher tel ou tel sprite en fonction du caractère lu.

Le contenu du fichier texte "modele.txt"

MMMMMMMMMMMMMMMMMMMMMMMMM
M                       M
MMMMMMM MMMMM MMMM MMMM M
M                       M
MMMMMMMMMM MMMMMMMMMMMMMM
M      MMM MM           M
MMMM M        MM MMM M MM
M  M MMMMMMMMMMM MMM M  M
M  M           M MMM M  M
M  MMMMM MMMMMMM MMM MMMM
M                       M
M MMMMMMMMM MMMMMM MMMMMM
M             MM       MM
MMMMMM MMMMMMMMMMM MMMMMM
MM MMM M                M
MM MMM M MMMMMMMMMMMMM MM
MM MMM           MMMMM MM
MM MMMMMMMMMMMM MMMMMM MM
MM                     MM
MMMMMM     MMMMMMMM MMMMM
MMMMMM MMMMMM       MMMMM
M         MMM MMMMM     M
MMMMMMMMM MMM MMMMMM    M
M                  MMMMMM
MMMMMMMMMMMMMMMMMMMMMMMMM

Chaque caractère est "M" ou " " (espace).

Il y a 25 lignes et chaque ligne comprend 25 caractères.

Le script de lecture du fichier texte

#nom du fichier : lire_modele.py
# script qui lit le fichier modele.txt 
with open("modele.txt", "r") as fichier:
  for ligne in fichier:
    for car in ligne:
      if car == 'M':
          print(car, end =' ')
      else  :
          print(' ',end=' ')       
    print()  # saut de ligne

Il faut donc deux boucles imbriquées : la boucle externe lit une ligne du fichier et la boucle interne lit chaque caractère de la ligne.
Notez que je n'utilise aucune méthode pour lire le fichier. Puisque l'objet "file" (nommé ici "fichier") est itérable j'utilise deux boucles pour lire chaque ligne et à l'intérieur de chaque ligne, chaque caractère.

Le rendu

M M M M M M M M M M M M M M M M M M M M M M M M M   
M                                               M   
M M M M M M M   M M M M M   M M M M   M M M M   M   
M                                               M   
M M M M M M M M M M   M M M M M M M M M M M M M M   
M             M M M   M M                       M   
M M M M   M                 M M   M M M   M   M M   
M     M   M M M M M M M M M M M   M M M   M     M   
M     M                       M   M M M   M     M   
M     M M M M M   M M M M M M M   M M M   M M M M   
M                                               M   
M   M M M M M M M M M   M M M M M M   M M M M M M   
M                           M M               M M   
M M M M M M   M M M M M M M M M M M   M M M M M M   
M M   M M M   M                                 M   
M M   M M M   M   M M M M M M M M M M M M M   M M   
M M   M M M                       M M M M M   M M   
M M   M M M M M M M M M M M M   M M M M M M   M M   
M M                                           M M   
M M M M M M           M M M M M M M M   M M M M M   
M M M M M M   M M M M M M               M M M M M   
M                   M M M   M M M M M           M   
M M M M M M M M M   M M M   M M M M M M         M   
M                                     M M M M M M   
M M M M M M M M M M M M M M M M M M M M M M M M M   

On affiche un beau labyrinthe !

Récapitulons

Modes d'ouverture d'un fichier

La fonction with open() ...as ... crée un "objectFile" et exige deux arguments : le chemin du fichier texte, le mode d'ouverture du fichier.

Le chemin du fichier se résume à son nom si le répertoire courant est celui qui contient le fichier texte.

Méthodes applicables à un objet de type file

Manipuler des fichiers structurés au format csv ou json

Le dossier "c:/python_prog" contient aussi des fichiers CSV (présentation tabulaire) et JSON (séquences de paires de clé:valeur).

Dans la console

>>> fichier = open("data3.csv")
>>> fichier.read()
"Durée,Date,Pouls,Pouls_max,Calories\n
60,'2020/12/01',110,130,409.1\n
60,'2020/12/02',117,145,479.0\n
60,'2020/12/03',103,135,340.0\n
45,'2020/12/04',109,175,282.4\n
45,'2020/12/05',117,148,406.0\n
60,'2020/12/06',102,127,300.0\n
60,'2020/12/07',110,136,374.0\n
450,'2020/12/08',104,134,253.3\n
30,'2020/12/09',109,133,195.1\n
60,'2020/12/10',98,124,269.0\n
60,'2020/12/11',103,147,329.3\n
60,'2020/12/12',100,120,250.7\n
60,'2020/12/12',100,120,250.7\n
60,'2020/12/13',106,128,345.3\n
60,'2020/12/14',104,132,379.3\n
60,'2020/12/15',98,123,275.0\n
60,'2020/12/16',98,120,215.2\n
60,'2020/12/17',100,120,300.0\n
45,'2020/12/18',90,112,\n
60,'2020/12/19',103,123,323.0\n
45,'2020/12/20',97,125,243.0\n
60,'2020/12/21',108,131,364.2\n
45,,100,119,282.0\n
60,'2020/12/23',130,101,300.0\n
45,'2020/12/24',105,132,246.0\n
60,'2020/12/25',102,126,334.5\n
60,20201226,100,120,250.0\n
...
"
>>> fichier.close()

Remarques

La méthode read() retourne une chaine unique ; difficile d'envisager un analyse des données.

Pour traiter des fichiers structurés au format CSV ou JSON il faut mieux utiliser respectivement les modules csv ou json ou mieux encore la bibliothèque pandas.
Je vous invite à lire le chapitre 16. Bibliothèque pandas pour fichiers CSV & JSON