[Mise à jour le : 16/5/2022]
and | continue | finally | is | raise |
as | def | for | lambda | return |
assert | del | from | None | True |
async | elif | global | nonlocal | try |
await | else | if | not | while |
break | except | import | or | with |
class | False | in | pass | yield |
Un fichier est un itérateur. Il est donc itérable puisqu'on peut le lire par une boucle for. Mais il est aussi son propre itérateur. Cela implique que l'on ne peut le parcourir qu'une fois dans une boucle for. Pour le reparcourir, il faut le fermer et l'ouvrir de nouveau. Ecrire deux boucles for imbriquées sur le même objet fichier ne fonctionnerait pas.
f = open(chemin\nomfichier, mode, encodage) # f : objet fichier # l'encodage ne concerne que les fichiers textuels
Cette fonction prend en paramètres :
Exemple : ouverture d'un fichier en lecture.
# La fonction open crée un objet de la classe TextIoWrapper. # On utilise les méthodes de cette classe pour interagir avec le fichier. # Lors d'une ouverture en lecture, le chemin et le fichier doivent exister # sinon une erreur FileNotFoundError est générée. f = open(r'data\fichier.txt','r',encoding='utf-8') # on transforme la chaîne en raw string en # plaçant un r devant pour désactiver tous les '\'
Exemple : ouverture d'un fichier en écriture.
f = open(r'data\fichier.txt','w',encoding='utf-8') # f : objet fichier
Exemple
f.close()
Exemple
# fichier.txt doit être présent dans le répertoire data sinon une erreur FileNotFoundError est générée. with open(r'data\fichier.txt','r',encoding='utf-8') as f: pass
f.write(chaine) # écrit le contenu de chaine dans le fichier et renvoie le nombre de caractères écrits.
Exemples
# Avec un `with' on garantit la fermeture du fichier # Si fichier.txt n'est pas présent dans le dossier data, il est créé # Ouverture du fichier en écriture (utf-8) with open(r'data\fichier.txt','w',encoding='utf-8') as f: for i in range(2): sortie.write(f"{i}\n") # Résultat : le fichier contient 0 1, un caractère par ligne # Ouverture en écriture en mode ajout # Ajout des valeurs 2 à 9 with open(r'data\foo.txt', 'a', encoding='utf-8') as sortie: for i in range(2,10): sortie.write(f"{i}\n") # Résultat le fichier contient 0 1 2 3 4 5 6 7 8 9, un caractère par ligne
Exemple 1a : ouverture avec with, on ne gère pas l'exception FileNotFoundError (à privilégier)
# foo.txt doit être présent dans le répertoire data sinon une erreur FileNotFoundError est générée. # foo.txt contient le texte 0 1 2 3 4 5 6 7 8 9, un caractère par ligne with open(r'data\foo.txt','r',encoding='utf-8') as f: contenu = f.read() # La totalité du fichier est placée dans une chaîne de caractères print(contenu) # résultat : 0 1 2 3 4 5 6 7 8 9, un caractère par ligne
Exemple 1b : ouverture avec with, on gère l'exception FileNotFoundError (à privilégier)
# foo.txt doit être présent dans le répertoire data sinon une erreur FileNotFoundError est générée. # foo.txt contient le texte 0 1 2 3 4 5 6 7 8 9, un caractère par ligne try: with open(r'data\foo.txt', 'r', encoding='utf-8') as f: # on essaie d'ouvrir le fichier contenu = f.read() # le fichier a été ouvert, on lit le contenu et print(contenu) # résultat : 0 1 2 3 4 5 6 7 8 9, un caractère par ligne except FileNotFoundError: print("Le fichier n'existe pas")
Exemple 1c : ouverture avec open(), fermeture avec close(), on ne gère pas l'exception FileNotFoundError
# foo.txt doit être présent dans le répertoire data sinon une erreur FileNotFoundError est générée. # foo.txt contient le texte 0 1 2 3 4 5 6 7 8 9, un caractère par ligne f = open(r'data\foo.txt','r',encoding='utf-8') contenu = f.read() # La totalité du fichier est placée dans une chaîne de caractères print(contenu) # résultat : 0 1 2 3 4 5 6 7 8 9, un caractère par ligne f.close()
Exemple 1d : ouverture avec open(), fermeture avec close(), on gère l'exception FileNotFoundError
# foo.txt doit être présent dans le répertoire data sinon une erreur FileNotFoundError est générée. # foo.txt contient le texte 0 1 2 3 4 5 6 7 8 9, un caractère par ligne try: f = open(r'data\foo.txt','r',encoding='utf-8') # on essaie d'ouvrir le fichier except FileNotFoundError: print("Le fichier n'existe pas") else: contenu = f.read() # le fichier a été ouvert, on lit le contenu et print(contenu) # résultat : 0 1 2 3 4 5 6 7 8 9, un caractère par ligne f.close()
\n n’est omis que sur la dernière ligne du fichier. Si f.readline() renvoie une chaîne vide, c’est que la fin du fichier a été atteinte, alors qu’une ligne vide est représentée par '\n' (une chaîne de caractères ne contenant qu’une fin de ligne).
Exemple
# fichier.txt doit être présent dans le répertoire data sinon une erreur FileNotFoundError est générée. with open(r'data\fichier.txt','r',encoding='utf-8') as f: a = f.readline() # Contenu de fichier.txt b = f.readline() # Première ligne print(a,b)
Exemple
# fichier.txt doit être présent dans le répertoire data sinon une erreur FileNotFoundError est générée. with open(r'data\fichier.txt','r',encoding='utf-8') as f: for line in f: print(line, end='')
Résultat attendu
# Contenu de fichier.txt
Première ligne
Deuxième ligne
Troisième ligne
A faire
Les données dans un programme Python sont stockées en mémoire (la RAM), sous une forme propice aux calculs. Par exemple un petit entier est fréquemment stocké en binaire dans un mot de 64 bits, qui est prêt à être soumis au processeur pour faire une opération arithmétique.
Ce format ne se prête pas forcément toujours à être transposé tel quel lorsqu'on doit écrire des données sur un support plus pérenne, comme un disque dur, ou encore sur un réseau pour transmission distante
Ainsi par exemple il pourra être plus commode d'écrire notre entier sur disque, ou de le transmettre à un programme distant, sous une forme décimale qui sera plus lisible.
Il convient donc de faire de la traduction dans les deux sens entre représentations d'une part en mémoire, et d'autre part sur disque ou sur réseau (à nouveau, on utilise en général les mêmes formats pour ces deux usages). Les plus utilisés sont json, csv, xml et pickle.
Dès que l'on souhaite enregistrer ou transmettre des types de données complexes comme des listes, des dictionnaires ou des instances de classes, le traitement précédent devient vite compliqué. Plutôt que de passer son temps à écrire et déboguer du code permettant de sauvegarder des types de données compliqués, on peut utiliser les modules pickle et json (JavaScript Object Notation) fournis par Python.
Le module pickle est à privilégier si l'on travaille uniquement en Python. Le format JSON étant normalisé, le module json est adapté à la sauvegarde de données devant être exploitées par d'autres langages.
Exemple 1 : sauvegarde d'un dictionnaire dans un fichier binaire avec le module pickle
import pickle # Création d'un dictionnaire scoreW = { "joueur 1" : 5, "joueur 2" : 10, "joueur 3" : 2 } # Enregistrement with open(r'data\donnees.pk','wb') as f: # l'extension .pk est optionnelle, ici choisie arbitrairement pck = pickle.Pickler(f) # Création de l'objet Pickler pck.dump(scoreW) # Enregistrement # Lecture de l'objet enregistré with open(r'data\donnees.pk','rb') as f: unpck = pickle.Unpickler(f) # Création de l'objet Unpickler scoreR = unpck.load() # Enregistrement # Affichage du dictionnaire relu après enregistrement print(scoreR) # résultat : {'joueur 1': 5, 'joueur 2': 10, 'joueur 3': 2} # On retrouve sa structure !
Exemple 2 : sauvegarde d'un dictionnaire dans un fichier texte avec le module json
import json # Création d'un dictionnaire scoreW = { "joueur 1": 5, "joueur 2": 10, "joueur 3": 2 } # Enregistrement with open(r'data\donnees.json', 'w') as f: json.dump(scoreW, f) # Lecture de l'objet enregistré with open(r'data\donnees.json', 'r') as f: scoreR = json.load(f) # Affichage du dictionnaire relu après enregistrement print(scoreR) # résultat : {'joueur 1': 5, 'joueur 2': 10, 'joueur 3': 2} # On retrouve sa structure !
Exemple 3 : limite de json pour python
import json # En partant d'une donnée construite à partir de types de base data = [ # des types qui ne posent pas de problème [1, 2, 'a', [3.23, 4.32], {'eric': 32, 'jean': 43}], # un tuple (1, 2, 3), ] # sauver ceci dans un fichier with open("s1.json","w", encoding='utf-8') as json_output: json.dump(data, json_output) # et relire le résultat with open("s1.json", encoding='utf-8') as json_input: data2 = json.load(json_input) print(data2) # Résultat : [[1, 2, 'a', [3.23, 4.32], {'eric': 32, 'jean': 43}], [1, 2, 3]] # le tuple (1,2,3) s'est transformé en liste [1,2,3]
Exemple 1
lines = "abc" + "\n" + "def" + "\n" print("abc" + "\n" + "def" + "\n") # Résultat # abc # def print(repr(lines)) # Résultat 'abc\ndef\n'
Exemple 2 : ouverture d'un fichier texte en binaire pour afficher les codes des caractères
with open(r'data\foo.txt', 'rb') as bytesfile: # on lit tout le contenu octets = bytesfile.read() # qui est de type bytes print("on a lu un objet de type", type(octets)) # si on regarde chaque octet un par un for i, octet in enumerate(octets): print(f"{i} → {repr(chr(octet))} [{hex(octet)}]") # Résultat partiel # 0 → '0' [0x30] # 1 → '\r' [0xd] # 2 → '\n' [0xa]
Les entrées-sorties sur fichier sont bien souvent bufferisées par le système d'exploitation. Cela signifie qu'un appel à write ne provoque pas forcément une écriture immédiate, car pour des raisons de performance on attend d'avoir suffisamment de matière avant d'écrire sur le disque.
Il y a des cas où ce comportement peut s'avérer gênant, et où on a besoin d'écrire immédiatement (et donc de vider le buffer), et c'est le propos de la méthode flush.
Depuis la version 3.4, en remplacement de os.path, la bibliothèque pathlib fournit dans une interface orientée objet unique des utilitaires pour parcourir l'arborescence de répertoires et fichiers.