Lire et écrire dans un fichier.

Créer un fichier et écrire dans ce fichier

Afin d'enregistrer à long terme (sur le disque dur, sur une clef usb...) des données (par exemple les scores d'un jeu écrit en python), python peut créer des fichiers et y inscrire des données.

Exemple.

Dans le programme suivant nous créons un fichier puis y inscrivons la table du 6 :


# création et ouverture d'un fichier texte 
# que l'on nomme table_du_6.txt
f=open('table_du_6.txt','w')


# Inscrire Table du 6 dans le fichier 
# et terminer la ligne :
f.write('Table du 6.\n')
# laisser une ligne blanche :
f.write('\n')


# pour j de 1 à 10
# inscrire 6*valeur(j)=valeur(6*j)
# et terminer la ligne 
for j in range(1,11) :
	f.write('6*{}={}.\n'.format(j, 6*j))
	
	
# à ne pas oublier sous peine de dysfonctionnement :
# fermer le fichier.
f.close()

Vous pouvez vérifier dans le répertoire (dossier) dans lequel se trouve votre programme qu'un fichier txt a été créé et qu'il contient les lignes suivantes :

Table du 6.

6*1=6.
6*2=12.
6*3=18.
6*4=24.
6*5=30.
6*6=36.
6*7=42.
6*8=48.
6*9=54.
6*10=60. 

Il est possible de créer le fichier dans un autre dossier que celui du programme. Nous n'en parlerons pas ici pour simplifier. Mais vous pouvez consulter par exemple les pages du cours de G. Swinnen.

Il est également possible d'utiliser with qui permet de ne pas avoir à gérer soi-même la fermeture du fichier ouvert. L'indentation joue alors un rôle important (le fichier ouvert joue dans ce cas le rôle d'une variable locale au bloc with, c'est ce qui autorise la possibilité d'une fermeture "automatique").


# création et ouverture d'un fichier texte 
# que l'on nomme table_du_6.txt
with open('table_du_6.txt','w') as f :


	# Inscrire Table du 6 dans le fichier 
	# et terminer la ligne :
	f.write('Table du 6.\n')
	# laisser une ligne blanche :
	f.write('\n')


	# pour j de 1 à 10
	# inscrire 6*valeur(j)=valeur(6*j)
	# et terminer la ligne 
	for j in range(1,11) :
		f.write('6*{}={}.\n'.format(j, 6*j))
		
		
# fermeture automatique du fichier
# en sortant du bloc de traitement de ce fichier (bloc with) 

Ouvrir un fichier existant et ajouter du texte

On suppose avoir créé un fichier nommé table.txt et y avoir inscrit la table du 6 par le programme suivant :


def inscrireTable(n) :
	f.write('Table du {}.\n'.format(n))
	f.write('\n')
	for j in range(1,11) :
		f.write('{}*{}={}.\n'.format(n,j, n*j))
	f.write('\n')
	f.write('\n')
	

f=open('tables.txt','w')
inscrireTable(6) 
f.close()

On aimerait maintenant ajouter la table du 7 à ce fichier tables.txt.

La première idée est de lancer :


def inscrireTable(n) :
	f.write('Table du {}.\n'.format(n))
	f.write('\n')
	for j in range(1,11) :
		f.write('{}*{}={}.\n'.format(n,j, n*j))
	f.write('\n')
	f.write('\n')
	

f=open('tables.txt','w')
inscrireTable(7) 
f.close()

Mais en ouvrant le fichier tables.txt, on se rend compte que la table du 6 précédemment inscrite a été écrasée et que seule la table du 7 est inscrite dans notre fichier.
Nous avons en effet ouvert notre fichier avec l'option 'w' dont le rôle est de créer le fichier avant de pouvoir écrire dedans. Si le fichier existait déjà, il est recréé, ce qui signifie que le fichier de même nom qui existait est écrasé au préalable.

Pour pouvoir ajouter du texte à la suite du texte existant, on ouvrira le fichier en mode ajout, c'est à dire avec l'option 'a'.

Pour tester cela, recréer le fichier ne contenant que la table du 6 en exécutant :


def inscrireTable(n) :
	f.write('Table du {}.\n'.format(n))
	f.write('\n')
	for j in range(1,11) :
		f.write('{}*{}={}.\n'.format(n,j, n*j))
	f.write('\n')
	f.write('\n')
	

f=open('tables.txt','w')
inscrireTable(6) 
f.close()

puis ajouter la table du 7 en exécutant :


def inscrireTable(n) :
	f.write('Table du {}.\n'.format(n))
	f.write('\n')
	for j in range(1,11) :
		f.write('{}*{}={}.\n'.format(n,j, n*j))
	f.write('\n')
	f.write('\n')
	

f=open('tables.txt','a')
inscrireTable(7) 
f.close()

Ouvrir ensuite le fichier tables.txt avec un éditeur de texte et constater que cette fois, le contenu initial n'a pas été écrasé.

Lire un fichier existant

On suppose disposer d'un fichier table8.txt dont le contenu est le suivant :

8*1=8.
8*2=16.
8*3=24.
8*4=32.
8*5=40.
8*6=48.
8*7=56.
8*8=64.
8*9=72.
8*10=80.

On suppose que 8*1=8. est la toute première ligne du fichier (pas de ligne blanche au-dessus).

On aimerait récupérer le contenu de ce fichier et placer chaque ligne dans une cellule d'une liste t :
t[0]='8*1=8.', t[1]='8*2=16.', ..., t[9]='8*10=80.'

Pour cela, il nous faut ouvrir le fichier en mode lecture (option 'r') puis utiliser l'instruction de lecture d'une ligne :


# création d'une liste vide 
t=[] 

# ouverture du fichier en lecture :
f=open('table8.txt','r')


# récupération des lignes 
for j in range(10) :
	ligneSuivante=f.readline()
	t.append(ligneSuivante)
 
# fermeture du fichier
f.close()


# impression de la liste pour contrôle :
print(t)

Ce qui donne :

['8*1=8.\n', '8*2=16.\n',
 '8*3=24.\n', '8*4=32.\n', '8*5=40.\n',
  '8*6=48.\n', '8*7=56.\n', '8*8=64.\n', '8*9=72.\n',
   '8*10=80.\n']

A l'affichage du résultat, on se rend compte que les fins de lignes font partie des lignes et sont donc récupérées en même temps que le contenu "réel" de la ligne. L'élément t[0] est ainsi la chaîne '8*1=8.\n'.

Si l'on veut récupérer le texte sans les fins de lignes, on pourra supprimer systématiquement le dernier caractère de chaque ligne :


# création d'une liste vide 
t=[] 

# ouverture du fichier en lecture :
f=open('table8.txt','r')


# récupération des lignes 
for j in range(10) :
	ligneSuivante=f.readline()[:-1]
	t.append(ligneSuivante)
 
# fermeture du fichier
f.close()


# impression de la liste pour contrôle :
print(t)

Ou mieux : on utilise la fonction rstrip qui permet de supprimer à la fin d'une chaîne les caractères désignés.


# création d'une liste vide 
t=[] 

# ouverture du fichier en lecture :
f=open('table8.txt','r')


# récupération des lignes 
for j in range(10) :
	ligneSuivante=f.readline().rstrip('\n')
	t.append(ligneSuivante)
 
# fermeture du fichier
f.close()


# impression de la liste pour contrôle :
print(t)

De façon plus concise :


# création d'une liste vide :
t=[] 

with open('table8.txt','r') as f :
	for ligne in f : t.append(ligne.rstrip('\n'))
 
# impression de la liste pour contrôle :
print(t)

Création automatique d'une liste des lignes du fichier.

Remarque : avec l'instruction readlines() (au pluriel cette fois), toutes les lignes sont récupérées en une fois dans une liste :


# ouverture du fichier en lecture :
f=open('table8.txt','r')


# récupération des lignes dans un tableau :
t=f.readlines()
 
# fermeture du fichier
f.close()


# impression de la liste pour contrôle :
print(t)

Ce qui donne :

['8*1=8.\n', '8*2=16.\n',
 '8*3=24.\n', '8*4=32.\n', '8*5=40.\n',
  '8*6=48.\n', '8*7=56.\n', '8*8=64.\n', '8*9=72.\n',
   '8*10=80.\n']

Stocker le contenu du fichier dans une variable de type str.

Il est possible également de récupérer l'intégralité du fichier en une seule chaîne de caractères :


# ouverture du fichier en lecture :
f=open('tables.txt','r')


# récupération du contenu du fichier dans une chaîne (string) :
chaine=f.read()
 
# fermeture du fichier
f.close()


# impression de la chaine pour vérif :
print(chaine)

On obtient la chaîne suivante :

8*1=8.
8*2=16.
8*3=24.
8*4=32.
8*5=40.
8*6=48.
8*7=56.
8*8=64.
8*9=72.
8*10=80.

Stocker un nombre donné de caractères dans une variable de type str.

L'instruction read(i) où i est un entier lira les i premiers caractères du fichier. Si une instruction read(10) est suivie d'une instruction read(3), la deuxième instruction lira les trois caractères qui se trouvent à la suite des 10 caractères déjà lus.

Par exemple (en utilisant toujours notre fichier contenant la table du 8) :


# ouverture du fichier en lecture :
f=open('tables.txt','r')


# récupération des 3 premiers caractères du fichier :
chaine=f.read(3)
# récupération des 20 caractères suivants :
chaine2=f.read(20)
 
# fermeture du fichier
f.close()


# impression de la chaine pour vérif :
print('Première chaîne lue : ', chaine)
print('\n')
print('Seconde chaîne lue :', chaine2)

donne :

Première chaîne lue :  8*1


Seconde chaîne lue : =8.
8*2=16.
8*3=24.

Traiter les variables de type autre que str

Avec la méthode write() et la méthode read() présentées ci-dessus, on ne peut écrire ou lire dans un fichier que des variables de type str.

Illustration :


# ouverture du fichier en écriture :
f=open('essai.txt','w')
a=3
print(f.write(a))
# fermeture du fichier
f.close()

Ce qui donne :

 print(f.write(a))
TypeError: must be str, not int

Pour inscrire la valeur de a dans le fichier, il nous faudra tout d'abord faire un cast avec la fonction str() :


# ouverture du fichier en lecture :
f=open('essai.txt','w')
a=3
print(f.write(str(a)))
# fermeture du fichier
f.close()

De la même façon, si on lit un fichier bidule.txt contenant les lignes suivantes :

4
5
6
12
20

la méthode read() récupérera des chaînes de caractères. Si l'on veut les utiliser comme entiers, on utilisera la fonction int().

Illustration :


# ouverture du fichier en lecture :
f=open('bidule.txt','r')
s=f.readline()
t=f.readlines()
for k in t :
	s+=k
# fermeture du fichier
f.close()

print(s)

donnera :

4
5
6
12
20

la première affectation s=f.readline() recopie la chaîne '4\n' dans s, l'instruction t=f.readlines() crée alors une liste de str contenant chacune des lignes suivantes (on a donc t=['5\n', '6\n', '12\n', '20\n', '\n']).
La boucle opère alors une concaténation de chaînes de caractères et s vaut, en sortie de boucle : s='4\n5\n6\n12\n20\n', ce qui s'affiche comme ci-dessus (les '\n' étant interprété comme des fins de ligne).

Si l'on veut calculer la somme des entiers apparaissant, on peut opérer ainsi :


# ouverture du fichier en lecture :
f=open('bidule.txt','r')
s=0
j=f.readline()
while j :
	s+=int(j)
	j=f.readline()
# fermeture du fichier
f.close()

print(s)

Ce qui donne :

47

Inscrire des variables et lire des variables en conservant leur type.

Pour cela, on pourra utiliser le module pickle.
Comme nous n'en aurons a priori pas la nécessité, nous ne développons pas ici d'exemples.

En cas de besoin, vous pourrez consulter le cours de G.Swinnen. ou le site de documentation de python.

Remarque

Un fichier texte est le moyen le plus simple d’échanger des matrices avec un tableur et il n’a pas besoin de modules dans ce cas. Lorsqu’on enregistre une feuille de calcul sous format texte, le fichier obtenu est organisé en colonnes : sur une même ligne, les informations sont disposées en colonne délimitées par un séparateur qui est souvent une tabulation (\t) ou un point virgule comme dans l’exemple suivant :


nom ; prénom ; livre
Hugo ; Victor ; Les misérables
Kessel ; Joseph ; Le lion
Woolf ; Virginia ; Mrs Dalloway
Calvino ; Italo ; Le baron perché

Pour lire ce fichier, il est nécessaire de scinder chaque ligne en une liste de chaînes de caractères, on utilise pour cela la méthode split des chaînes de caractères.


mat = [ ] 			# création d’une liste vide,
f = open ("essai.txt", "r") 	# ouverture du fichier en mode lecture
for li in f : 			# pour toutes les lignes du fichier
   s = li.strip ("\n\r") 		# on enlève les caractères de fin de ligne
   l = s.split (";") 		# on découpe en colonnes
   mat.append (l) 		# on ajoute la ligne à la matrice
f.close () 			# fermeture du fichier

Ce format de fichier texte est appelé CSV3, il peut être relu depuis un programme Python comme le montre l’exemple précédent ou être chargé depuis Microsoft Excel en précisant que le format du fichier est le format CSV. Pour les valeurs numériques, il ne faut pas oublier de convertir en caractères lors de l’écriture et de convertir en nombres lors de la lecture.

Remarque : nombres français et anglais

Les nombres réels s’écrivent en anglais avec un point pour séparer la partie entière de la partie décimale.
En français, il s’agit d’une virgule. Il est possible que, lors de la conversion d’une matrice, il faille remplacer les points par des virgules et réciproquement pour éviter les problèmes de conversion.