Différences
Ci-dessous, les différences entre deux révisions de la page.
Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
python:bases:fichiers [2021/06/30 20:57] – [Quiz] phil | python:bases:fichiers [2022/09/03 10:40] (Version actuelle) – [Python - Fichiers] phil | ||
---|---|---|---|
Ligne 1: | Ligne 1: | ||
+ | {{ : | ||
+ | ===== Python - Fichiers ===== | ||
+ | [Mise à jour le : 16/5/2022] | ||
+ | |||
+ | * **Sources** | ||
+ | * **Documentation** sur Python.org : < | ||
+ | |||
+ | * **Lectures connexes** | ||
+ | * **Real Python** | ||
+ | - < | ||
+ | - < | ||
+ | |||
+ | * **Mots-clés** : itérateur, ouverture, lecture, écriture, fermeture, module pickle, context manager. | ||
+ | |||
+ | <callout type=" | ||
+ | |||
+ | | and | continue | ||
+ | | **as** | ||
+ | | assert | ||
+ | | __async__ | ||
+ | | __await__ | ||
+ | | break | except | ||
+ | | class | __False__ | ||
+ | |||
+ | * < | ||
+ | * **Modules** utilisées dans les exemples : **pathlib**, | ||
+ | |||
+ | ---- | ||
+ | |||
+ | ==== 1. Généralités ==== | ||
+ | Un fichier est un **itérateur**. Il est donc **itérable** puisqu' | ||
+ | |||
+ | ==== 2. Ouvrir un fichier ==== | ||
+ | <callout type=" | ||
+ | |||
+ | <code python *.py> | ||
+ | f = open(chemin\nomfichier, | ||
+ | # l' | ||
+ | </ | ||
+ | |||
+ | Cette fonction prend en paramètres : | ||
+ | * le **chemin** (absolu ou relatif) menant au fichier visé // | ||
+ | * le **mode** d' | ||
+ | * **' | ||
+ | * **' | ||
+ | * **' | ||
+ | * l' | ||
+ | |||
+ | <callout type=" | ||
+ | |||
+ | //Exemple// : ouverture d'un fichier **en lecture**. | ||
+ | |||
+ | <code python *.py> | ||
+ | # 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' | ||
+ | # plaçant un r devant pour désactiver tous les ' | ||
+ | </ | ||
+ | |||
+ | //Exemple// : ouverture d'un fichier **en écriture**. | ||
+ | |||
+ | <code python *.py> | ||
+ | f = open(r' | ||
+ | </ | ||
+ | |||
+ | <callout type=" | ||
+ | |||
+ | ==== 3. Fermer un fichier ==== | ||
+ | <callout icon=" | ||
+ | |||
+ | //Exemple// | ||
+ | |||
+ | <code python .py> | ||
+ | f.close() | ||
+ | </ | ||
+ | |||
+ | ==== 4. Ouvrir et fermer automatiquement un fichier avec with ==== | ||
+ | |||
+ | <callout type=" | ||
+ | |||
+ | //Exemple// | ||
+ | <code python *.py> | ||
+ | # fichier.txt doit être présent dans le répertoire data sinon une erreur FileNotFoundError est générée. | ||
+ | with open(r' | ||
+ | pass | ||
+ | </ | ||
+ | |||
+ | ==== 5. Ecrire dans un fichier ==== | ||
+ | <callout type=" | ||
+ | |||
+ | <code python *.py> | ||
+ | f.write(chaine) # écrit le contenu de chaine dans le fichier et renvoie le nombre de caractères écrits. | ||
+ | </ | ||
+ | |||
+ | // | ||
+ | |||
+ | <code python *.py> | ||
+ | # 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' | ||
+ | for i in range(2): | ||
+ | sortie.write(f" | ||
+ | |||
+ | # Ouverture en écriture en mode ajout | ||
+ | # Ajout des valeurs 2 à 9 | ||
+ | with open(r' | ||
+ | for i in range(2, | ||
+ | sortie.write(f" | ||
+ | </ | ||
+ | |||
+ | <callout icon=" | ||
+ | |||
+ | ==== 6. Lire le contenu d'un fichier ==== | ||
+ | === 6.1 Lire l' | ||
+ | |||
+ | <callout type=" | ||
+ | |||
+ | // Exemple 1a // : ouverture avec **with**, on ne gère pas l' | ||
+ | |||
+ | <code python *.py> | ||
+ | # 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' | ||
+ | contenu = f.read() # La totalité du fichier est placée dans une chaîne de caractères | ||
+ | print(contenu) | ||
+ | </ | ||
+ | |||
+ | // Exemple 1b // : ouverture avec **with**, on gère l' | ||
+ | |||
+ | <code python .py> | ||
+ | # 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' | ||
+ | contenu = f.read() | ||
+ | print(contenu) | ||
+ | except FileNotFoundError: | ||
+ | print(" | ||
+ | </ | ||
+ | |||
+ | // Exemple 1c // : ouverture avec **open**(), fermeture avec **close**(), | ||
+ | |||
+ | <code python *.py> | ||
+ | # 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' | ||
+ | contenu = f.read() # La totalité du fichier est placée dans une chaîne de caractères | ||
+ | print(contenu) | ||
+ | f.close() | ||
+ | </ | ||
+ | |||
+ | // Exemple 1d // : ouverture avec **open**(), fermeture avec **close**(), | ||
+ | |||
+ | <code python .py> | ||
+ | # 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' | ||
+ | except | ||
+ | print(" | ||
+ | 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() | ||
+ | </ | ||
+ | |||
+ | |||
+ | <callout type=" | ||
+ | |||
+ | === 6.2 Lecture du fichier ligne par ligne === | ||
+ | <callout type=" | ||
+ | |||
+ | > **\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 ' | ||
+ | |||
+ | //Exemple// | ||
+ | |||
+ | <code python *.py> | ||
+ | # fichier.txt doit être présent dans le répertoire data sinon une erreur FileNotFoundError est générée. | ||
+ | with open(r' | ||
+ | a = f.readline() # Contenu de fichier.txt | ||
+ | b = f.readline() # Première ligne | ||
+ | print(a,b) | ||
+ | </ | ||
+ | |||
+ | <callout type=" | ||
+ | |||
+ | //Exemple// | ||
+ | |||
+ | <code python *.py> | ||
+ | # fichier.txt doit être présent dans le répertoire data sinon une erreur FileNotFoundError est générée. | ||
+ | with open(r' | ||
+ | for line in f: | ||
+ | print(line, end='' | ||
+ | </ | ||
+ | |||
+ | //Résultat attendu// | ||
+ | > # Contenu de fichier.txt | ||
+ | > Première ligne | ||
+ | > Deuxième ligne | ||
+ | > Troisième ligne | ||
+ | |||
+ | <callout type=" | ||
+ | |||
+ | |||
+ | ====7. Fichier binaire ==== | ||
+ | A faire | ||
+ | |||
+ | ==== 8. Enregistrer un objet dans un fichier ==== | ||
+ | * **Problème** | ||
+ | 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' | ||
+ | |||
+ | Ainsi par exemple il pourra être plus commode d' | ||
+ | |||
+ | Il convient donc de faire de la traduction dans les deux sens entre représentations d'une part en mémoire, et d' | ||
+ | |||
+ | 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, | ||
+ | |||
+ | 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' | ||
+ | |||
+ | //Exemple 1// : sauvegarde d'un dictionnaire dans un fichier binaire avec le module //pickle// | ||
+ | |||
+ | * **source** : < | ||
+ | |||
+ | <code python *.py> | ||
+ | import pickle | ||
+ | |||
+ | # Création d'un dictionnaire | ||
+ | scoreW = { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | |||
+ | # Enregistrement | ||
+ | with open(r' | ||
+ | pck = pickle.Pickler(f) # Création de l' | ||
+ | pck.dump(scoreW) # Enregistrement | ||
+ | |||
+ | # Lecture de l' | ||
+ | with open(r' | ||
+ | unpck = pickle.Unpickler(f) # Création de l' | ||
+ | scoreR = unpck.load() # Enregistrement | ||
+ | |||
+ | # Affichage du dictionnaire relu après enregistrement | ||
+ | print(scoreR) | ||
+ | # On retrouve sa structure ! | ||
+ | </ | ||
+ | |||
+ | //Exemple 2// : sauvegarde d'un dictionnaire dans un fichier texte avec le module //json// | ||
+ | |||
+ | * **source** : < | ||
+ | |||
+ | <code python *.py> | ||
+ | import json | ||
+ | |||
+ | # Création d'un dictionnaire | ||
+ | scoreW = { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } | ||
+ | |||
+ | # Enregistrement | ||
+ | with open(r' | ||
+ | json.dump(scoreW, | ||
+ | |||
+ | # Lecture de l' | ||
+ | with open(r' | ||
+ | scoreR = json.load(f) | ||
+ | |||
+ | # Affichage du dictionnaire relu après enregistrement | ||
+ | print(scoreR) | ||
+ | # On retrouve sa structure ! | ||
+ | </ | ||
+ | |||
+ | // Exemple 3 // : limite de json pour python | ||
+ | <code python *.py> | ||
+ | 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, ' | ||
+ | # un tuple | ||
+ | (1, 2, 3), | ||
+ | ] | ||
+ | |||
+ | # sauver ceci dans un fichier | ||
+ | with open(" | ||
+ | json.dump(data, | ||
+ | |||
+ | # et relire le résultat | ||
+ | with open(" | ||
+ | data2 = json.load(json_input) | ||
+ | print(data2) # Résultat : [[1, 2, ' | ||
+ | # le tuple (1,2,3) s'est transformé en liste [1,2,3] | ||
+ | </ | ||
+ | |||
+ | <callout icon=" | ||
+ | car ils ne sont pas natifs en JavaScript), | ||
+ | - **tuple**, qui se fait encoder comme une liste ; \\ | ||
+ | - **complex**, | ||
+ | ==== 9. Les built-in repr() et flush() ==== | ||
+ | |||
+ | * **repr()** permet d' | ||
+ | |||
+ | //Exemple 1// | ||
+ | |||
+ | <code python *.py> | ||
+ | lines = " | ||
+ | print(" | ||
+ | # abc | ||
+ | # def | ||
+ | print(repr(lines)) | ||
+ | </ | ||
+ | |||
+ | //Exemple 2// : ouverture d'un fichier texte en binaire pour afficher les codes des caractères | ||
+ | <code python *.py> | ||
+ | with open(r' | ||
+ | # on lit tout le contenu | ||
+ | octets = bytesfile.read() | ||
+ | # qui est de type bytes | ||
+ | print(" | ||
+ | # si on regarde chaque octet un par un | ||
+ | for i, octet in enumerate(octets): | ||
+ | print(f" | ||
+ | # 0 → ' | ||
+ | # 1 → ' | ||
+ | # 2 → ' | ||
+ | </ | ||
+ | |||
+ | * **flush()** | ||
+ | |||
+ | Les entrées-sorties sur fichier sont bien souvent bufferisées par le système d' | ||
+ | |||
+ | Il y a des cas où ce comportement peut s' | ||
+ | |||
+ | ====10. Utilitaires ==== | ||
+ | Depuis la version 3.4, en remplacement de os.path, la bibliothèque < | ||
+ | ---- | ||
+ | |||
+ | ==== Résumé ==== | ||
+ | * On ouvre un fichier en utilisant la fonction **open** prenant en paramètre le chemin vers le fichier, le mode d' | ||
+ | * On lit dans un fichier en utilisant la méthode **read** et on écrit avec la méthode **write**. | ||
+ | * Un fichier doit être refermé après usage avec la méthode **close** ou automatiquement avec la syntaxe de **with**. Cette deuxième méthode est recommandée en Python moderne. | ||
+ | * Le module **pickle** est utilisé pour enregistrer des objets Python dans des fichiers et les recharger ensuite. | ||
+ | |||
+ | ---- | ||
+ | |||
+ | {{ : | ||
+ | ==== Quiz ==== | ||
+ | * < | ||
+ | * < | ||
+ | |||
+ | ---- | ||
+ | |||
+ | {{ : | ||
+ | ====Pour aller plus loin ... ==== | ||
+ | * < | ||
+ | * < | ||
+ | * **CSV** | ||
+ | * < | ||
+ | * < | ||
+ | * < | ||
+ | * < | ||
+ | * < |