python fichier

Identification

Infoforall

20 - Enregister et lire des fichiers


Vous savez maintenant qu'il existe plusieurs encodages possibles pour les caractères. Nous avons fait des activités sur les stuctures de données et sur le format CSV. Mais comment enregistre-t-on des données ? Un dictionnaire par exemple...

Prérequis : Python - Encodage des textes.

Logiciel nécessaire pour l'activité : Python 3 : Thonny, IDLE ...

Evaluation ✎ : questions 08-09-10-11-12

1 - Création d'un fichier

01° Enregistrer ce script dans un répertoire qu'on nommera activiteFichier.

📁 activiteFichier

📄 script_test.py

1 2 3 4 5 6 7 8 9
# 1 - Création de l'objet-fichier : ouverture en mode w (write) obj_fichier = open('aaa.txt', 'w', encoding="utf-8") # 2 - Remplissage progressif du fichier obj_fichier.write("Premier contenu") obj_fichier.write("Deuxième ajout") # 3 - Fermeture de l'objet-fichier obj_fichier.close()

Utiliser le script. Regarder le contenu de votre répertoire : vous devriez constater la présence d'un nouveau fichier nommée 'aaa.txt' dans votre répertoire.

📁 activiteFichier

📄 script_test.py

📄 aaa.txt

02° Ouvrir le fichier-texte pour voir son contenu. Que voyez-vous de surprenant ?

...CORRECTION...

Voici le contenu :

Première ligneDeuxième ligne

On constate donc qu'il n'y a pas de passage à la ligne. Alors qu'on aurait pu le croire. La méthode write porte donc bien son nom : on écrit des octets dans le fichier. Si on ne signale pas qu'il faut insérer l'octet signalant le passage à la ligne, on ne le rajoute pas automatiquement !

Comme vous avez dû le voir, la méthode write ne fait que rajouter le contenu, sans chercher à rajouter de passage à la ligne.

Si vous voulez rajouter les passages à la ligne, il faudra le dire, en rajoutant des passages à la ligne  \n  dans votre string une fois que vous avez fini une ligne.

Tentons avec cette méthode.

03° Tester le script suivant dans lequel nous tentons cette fois de rajouter des passages à la ligne. Ouvrir le fichier-texte après avoir exécuté le script. Qu'est-ce qui est surprenant ?

1 2 3 4 5 6 7 8 9
# 1 - Création de l'objet-fichier : ouverture en mode w (write) obj_fichier = open('aaa.txt', 'w', encoding="utf-8") # 2 - Remplissage progressif du fichier obj_fichier.write("Voici une nouvelle ligne\n") obj_fichier.write("Cette fois, c'est la dernière ligne du fichier.\n") # 3 - Fermeture de l'objet-fichier obj_fichier.close()

...CORRECTION...

Voici le contenu :

Voici une nouvelle ligne Cette fois, c'est la dernière ligne du fichier.

Le nouveau contenu a supprimé le premier contenu !

Alors comment faire pour rajouter du contenu et non pas le supprimer à chaque fois qu'on ouvre le fichier à nouveau ?

Tout vient de l'argument qu'on fournit en plus du nom du fichier.

open('aaa.txt', 'w') permet de créer un lien vers le contenu physique du fichier en remplacant l'éventuel contenu précédent.
'w', pour WRITE.

open('aaa.txt', 'a') permet de créer un lien vers le contenu physique mais d'y rajouter du contenu.
'a' pour APPEND.

04° Créer un script qui permet cette fois de rajouter deux lignes au fichier 'aaa.txt'.

...CORRECTION...

Le fichier est déjà créé. Il suffit donc d'utiliser l'argument 'a' et pas l'argument 'w.

1 2 3 4 5 6 7 8 9
# 1 - Création de l'objet-fichier : ouverture en mode a (append) obj_fichier = open('aaa.txt', 'a', encoding="utf-8") # 2 - Remplissage progressif du fichier obj_fichier.write("Et cette fois, on supprime ou pas ?\n") obj_fichier.write("Ah ben non? On rajoute.\n") # 3 - Fermeture de l'objet-fichier obj_fichier.close()

Voici le contenu obtenu après exécution :

Voici une nouvelle ligne Cette fois, c'est la dernière ligne du fichier. Et cette fois, on supprime ou pas ? Ah ben non? On rajoute.

Nous savons donc maintenant créer un fichier-texte ou rajouter des caractères à la suite des précédents.

2 - Lecture ligne par ligne d'un fichier

Voyons comment lire les caractères de notre fichier.

Cette fois, nous allons l'ouvrir avec l'argument 'r' pour READ. La liaison sera ainsi effectuée uniquement en lecture.

05° Utiliser le script suivant : il va vous permettre de lire et afficher les 4 lignes du fichier : la méthode readline() va transmettre le flux de son point actuel (le début du fichier au départ) jusqu'à rencontrer un passage à la ligne  \n .

Ici, chaque ligne sera simplement affichée sur la console à l'aide de la fonction native print.

1 2 3 4 5 6 7 8 9 10 11
# 1 - Création de l'objet-fichier : ouverture en mode r (read) obj_fichier = open('aaa.txt', 'r', encoding="utf-8") # 2 - Lecture progressive du fichier print(obj_fichier.readline(), end="") print(obj_fichier.readline(), end="") print(obj_fichier.readline(), end="") print(obj_fichier.readline(), end="") # 3 - Fermeture de l'objet-fichier obj_fichier.close()

Exécuter ce script vous permettra d'obtenir ceci dans le Shell :

Voici une nouvelle ligne Cette fois, c'est la dernière ligne du fichier. Et cette fois, on supprime ou pas ? Ah ben non? On rajoute.

Avec cette façon de faire, si on a 1500 lignes, on est parti pour taper 1500 fois print... Heureusement, notre objet-fichier obj_fichier est un itérable : on peut utiliser une boucle FOR.

06° Utiliser ce script de lecture : il va vous permettre de lire et afficher en boucle les "lignes" du fichier.

En première ligne, on notera qu'on demande le type de l'objet-fichier obj_fichier. Quel est son type ? Est-ce un simple texte ?

1 2 3 4 5 6 7 8 9 10
# 1 - Création de l'objet-fichier : ouverture en mode w obj_fichier = open('aaa.txt', 'r', encoding="utf-8") print(type(obj_fichier)) # 2 - Remplissage progressif du fichier for ligne in obj_fichier : print(ligne, end="") # 3 - Fermeture de l'objet-fichier obj_fichier.close()

...CORRECTION...

Cet objet est de type TextIOWrapper. Il s'agit d'un objet gestionnaire de flux entrant (input)-sortant(output). Il ne s'agit donc pas directement du texte ou du fichier mais d'un objet informatique permettant d'interagir avec le fichier dont les octets sont enregistrés en mémoire.

obj_fichier est un objet capable de faire interface entre notre programme et le fichier réel (la suite d'octets).

Que fait la méthode readline ? Elle va fournir la chaîne de caractères qu'on lit dans le fichier entre la position actuelle et le prochain LINE FEED  \n  rencontré.

Mais on peut également juste lire les caractères un par un avec la méthode read qui permet de lire le flux de données en fonction d'un nombre de caractères plutôt que d'aller nécessairement jusqu'au prochain LINEFEED. On fournira en arguement le nombre de caractères à lire. Si on ne précise pas d'argument, la méthode va renvoyer... la totalité du flux.

07° Utiliser ce script de lecture : il va vous permettre de lire le caractère un par un. On affiche chaque caractère, à part les a qu'on décide de remplacer par @.

On utilise un print dont le caractère final est une étoile, de façon à bien voir les successions de lecture.

Utiliser le script pour visualiser le résultat.

A quoi voit-on que l'espace est bien un caractère comme un autre ?

A quoi voit-on que le LINE FEED est bien un caractère comme un autre ?

Modifier alors le programme pour qu'il gère 5 caractères à la fois.

1 2 3 4 5 6 7 8 9 10 11 12 13
# 1 - Création de l'objet-fichier : ouverture en mode w obj_fichier = open('aaa.txt', 'r', encoding="utf-8") # 2 - Remplissage progressif du fichier lecture = "o" # Affectation quelconque pour rentrer une première fois dans la boucle while lecture : lecture = obj_fichier.read(1) if lecture == 'a' or lecture == 'A' : lecture = '@' print(lecture, end="*") # 3 - Fermeture de l'objet-fichier obj_fichier.close()

...CORRECTION...

On obtient cet affichage :

V*o*i*c*i* *u*n*e* *n*o*u*v*e*l*l*e* *l*i*g*n*e* *C*e*t*t*e* *f*o*i*s*,* *c*'*e*s*t* *l*@* *d*e*r*n*i*è*r*e* *l*i*g*n*e* *d*u* *f*i*c*h*i*e*r*.* *E*t* *c*e*t*t*e* *f*o*i*s*,* *o*n* *s*u*p*p*r*i*m*e* *o*u* *p*@*s* *?* *@*h* *b*e*n* *n*o*n*?* *O*n* *r*@*j*o*u*t*e*.* **

On voit bien que l'espace est un caractère puisqu'il y a apparition d'une étoile derrière chaque caractère dans le code et que derrière les espaces on trouve bien ... une étoile.

Idem pour les passages à la ligne (LINE FEED). Le caractère provoque le passage à la ligne car c'est un caractère de contrôle et pas juste un caractère d'imprimerie. Par contre, en début de ligne, on constate qu'il y a ... une étoile. Le LINEFEED est donc bien un caractère.

Si on lance le code en lisant 5 caractères à la fois en ligne 7, on obtient ceci :

Voici* une *nouve*lle l*igne *Cette* fois*, c'e*st la* dern*ière *ligne* du f*ichie*r. Et* cett*e foi*s, on* supp*rime *ou pa*s ? A*h ben* non?* On r*ajout*e. **

Une dernière chose avec la lecture : pour lire un fichier-texte, il faut en réalité se rendre compte qu'on lit des octets et qu'on les décode en respectant un certain encodage.

Ici, nous avons créé le fichier en utilisant l'encodage UTF-8 (de 1 à 4 octets par caractère, en fonction du caractère commun ou pas du caractère).

Il faudrait donc le lire en décodant le fichier en UTF-8 également.

✎ 08° Lire et utiliser le script suivant qui crée un fichier en UTF-8 et qui ouvre un flux vers ce même fichier en le lisant en UFT-8.

Modifier alors le fichier pour le créer en UTF-8 mais en le lisant en iso8859_15 (également nommée latin-9) : la table un octet pour l'europe de l'Ouest, mise à jour avec l'euro.

Fournir le code du nouveau script.

Ci-dessous le script initial et le résultat attendu avant et après modification.

1 2 3 4 5 6 7 8 9 10
# 1 - Ecriture du fichier obj_fichier = open('perceval.txt', 'w', encoding="utf-8") obj_fichier.write("C'est écrit en UTF-8 ? De toutes manières, j'ai jamais compris à vos histoires d'encodage.") obj_fichier.close() # 2 - lecture du fichier obj_fichier = open('perceval.txt', 'r', encoding="utf-8") for ligne in obj_fichier : print(ligne) obj_fichier.close()

Affichage avec écriture en UTF-8 et lecture en UTF-8 :

C'est écrit en UTF-8 ? De toutes manières, j'ai jamais compris à vos histoires d'encodage.

Affichage avec écriture en UTF-8 et lecture en iso8859_15 :

C'est écrit en UTF-8 ? De toutes maniÚres, j'ai jamais compris à vos histoires d'encodage.

3 - Actions sur les strings

Maintenant que vous savez créer des fichiers (avec 'w'), rajouter des choses dans les fichiers (avec 'a'), et lire les fichiers avec (avec 'r'), nous allons pouvoir créer des fichiers en surveillant de près ce qu'on lit ou ce qu'on écrit.

Cette partie présente un rapide exposé de quelques méthodes qu'on retrouve souvent dans les applications gérant les entrées / sorties de type texte.

Rappel : actions et tests sur les strings

Revoyons quelques actions bien pratiques et assez pratique.

Tester si un string fini par .txt ?

C'est toujours pratique de vérifier l'extension d'un fichier.

Il existe une méthode endswith des strings qui sert à ça :

>>> nom = 'perceval.txt' >>> nom.endswith('.txt') True >>> nom.endswith('.png') False

On peut aussi juste vérifier que les 4 derniers caractères correspondent bien à .txt.

>>> nom = "perceval.txt" >>> nom[-4:] == '.txt' True >>> nom[-4:] == '.png' False

Tester si un string contient toto ?

Pratique aussi pour savoir si un mot-clé apparaît bien dans une séquence.

>>> nom = "Merlin ou toto l'asticot" >>> 'toto' in nom True >>> 'grand magicien' in nom False

Transformer un string en majuscules ou en minuscules ?

Pratique pour vérifier si un texte contient le nom Toto sans tester toto, TOTO et Toto...

On peut utiliser les méthodes upper et lower qui renvoie une copie du string.

Regardez bien la majuscule dans le nom suivant :

>>> nom = "Merlin ou Toto l'asticot" >>> 'toto' in nom False >>> 'toto' in nom.lower() True >>> nom "Merlin ou Toto l'asticot"
>>> nom = "Merlin ou Toto l'asticot" >>> 'TOTO' in nom False >>> 'TOTO' in nom.upper() True >>> nom "Merlin ou Toto l'asticot"

Si vous voulez voir les autres méthodes, vous pouvez aller voir cette fiche ou faire des recherches sur le Web :

FICHE STRINGS

Expressions régulières

Cette partie va aller vite. Non pas car c'est simple mais parce qu'il y a trop à dire ! Je veux juste vous montrer quelques exemples, au cas où vous voudriez faire quelque chose de similaire. Vous aurez au moins vu les bases.

Les expressions régulières sont un moyen de trouver des motifs dans un string.

On notera juste qu'un peu fournir entre crochet l'ensemble des caractères qu'on veut voir. Par exemple, dans une expression régulière [0-9] veut dire qu'on attend un caractère numérique (0-1-2-3-4-5-6-7-8-9) et un seul.

On peut ensuite donner entrea accolades le nombre de fois où on cherche ce caractère. Ainsi, [0-9]{2} veut dire qu'on accepte 08, 75 ou 42 mais pas 7A.

On peut également entourer nos ensembles entre parenthèses pour les préciser encore un peu plus : ([0-9]{2}-) veut dire qu'on cherche des séquences comme 78- ou 12- ou 06- mais pas Av?.

Un exemple pour la recherche d'un numéro de téléphone dans un texte.

>>> texte = "Le numéro de Toto l'asticot est 06-07-06-07-06..." >>> import re >>> sequence = "([0-9]{2}-){4}([0-9]{2}){1}" >>> re.search(sequence, texte) <re.Match object; span=(32, 43), match='06-07-06-07'> >>> if re.search(sequence, texte) : print('Ce texte contient un numéro de téléphone') Ce texte contient un numéro de téléphone >>> trouve = re.search(sequence, texte) >>> trouve.group() '06-07-06-07-06'

On notera que la réponse de la méthode search est un objet complexe de classe Match qui contient notamment les index du début et de la fin du motif trouvé.

On peut accéder au(x) string(s) trouvé(s) en utilisant la méthode group sur cet objet.

✎ 09° Expliquer ce que fait ce programme étape par étape.

Analyser la ligne 5 avec précision : dans quels cas parvient-on à sortir de la boucle ? Décrire les réponses possibles permettant de sortir de la boucle.

Qu'aurions-nous pu mettre à la place de "o" en ligne 3 ?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
fichier = open('musique.csv', 'a', encoding='utf-8') continuer = "o" while continuer.lower() != 'n' : titre = input("Entrer le titre de la chanson : ") artiste = input("Entrer le nom du chanteur / groupe : ") sortie = input("Date de sortie (format MM-AAAA) : ") genre = input("Genre musical : ") note = input("Votre notation (de 0 (nul) à 5 (excellent)") url = input("Obligatoire : une URL pour l'écouter ou avoir des infos ?") enregistrement = f"{titre};{artiste};{sortie};{genre};{note};{url}" fichier.write(enregistrement+'\n') continuer = input("Nouvelle entrée (O/N) ? ") fichier.close()

✎ 10° Qu'est-ce que le format CSV, Comma Separated Value ?

  • A : Un format libre de musique, une alternative à MP3.
  • B : Un format texte permettant de comprimer les données.
  • C : Un format d'enregistrement simple de données où chaque enregistrement prend une ligne et où les éléments sont séparés par des virgules
  • D : Il y a une faute dans l'énoncé. C'est Coma Separated Value en réalité. C'est un format de données presque abandonné, qui est comateux.

On demande d'enregistrer des choses. C'est fait. Mais comment les lire ?

✎ 11° Fournir un autre programme, capable de lire ligne par ligne les enregistrements dans le fichier que nous venons de créer.

Si vous avez du courage, vous pouvez aller jusqu'à créer un affichage plus joli en récupérant les différents attributs en utilisant la méthode split qui divise le string en utilisant un caractère séparateur et renvoie un tableau.

>>> entree = "aaa;bbb;ccc;ddd" >>> champs = entree.split(";") >>> champs ['aaa', 'bbb', 'ccc', 'ddd'] >>> champs[0] 'aaa'

Dernière "petite" chose : la validation des entrées. Il ne sert à rien d'enregistrer des données sans être certain de ce qu'à rentrer l'utilisateur. Si on vous demande une date et qu'on stocke 28 juin 1995, nous allons être bien géné lorsqu'il faudra traiter les données si on voulait 06-1995.

✎ 12° Tenter de créer un test sur la date pour ne pas enregistrer la demande si la date ne respecte pas ce format.

4 - Lecture octet par octet

Cette partie ne vise qu'à vous montrer ce qu'est en réalité un fichier (texte ou pas). Rien n'est à retenir par coeur.

Vous avez certainement déjà compris le principe du fichier en tant que suite d'octets. Nous allons ici manipuler le concept pour bien l'appréhender.

Nous avons vu que votre fichier n'est au final qu'une suite d'octets.

Ca tombe bien : Python est capable de lire les octets du fichier plutôt que de tenter de les interpréter-décoder sous forme d'un texte. Pour cela, il faut créer votre objet-fichier avec un argument contenant 'r', comme binaire. Ainsi pour lire les octets, il suffit d'ouvrir le fichier avec 'rb'.

Nous utiliserons deux méthodes :

  • la méthode read qui permet de lire un certain nombre d'octets dans le flux.
  • la méthode tell qui renvoie la position du pointeur sur le fichier.

13° Utiliser ce script qui crée un fichier en l'encodant en iso8859_15 et qui l'ouvre ensuite en lecture binaire de façon à voir le contenu octet par octet.

On utilise l'affichage Python usuel des bytes : si la valeur est inférieure à 128, on affiche le caractère ASCII correspondant.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# Création et fermeture du fichier fichier = open('lecture.txt', 'w', encoding="iso8859_15") fichier.write("Dernière partie.\n") fichier.close() # Ouverture du fichier en mode byte fichier = open('lecture.txt', 'br') # Affichage en utilisant l'affichage standard des bytes en Python octet = b'0' while octet : position = fichier.tell() # On mesure la position du pointeur de lecture octet = fichier.read(1) # On lit un octet dans le flux if octet : print(f"Position dans le fichier {position}. Lecture : ", octet) # Fermeture du fichier fichier.close()

Questions

  1. Ligne 5 : Qu'est-ce qui montre qu'on ouvre le fichier en mode binaire et pas en mode texte ?
  2. Ligne 8 : pourquoi créé une variable octet à cette endroit pour y mettre "n'importe quoi" ?
  3. Combien d'octets dans ce fichier ?

...CORRECTION...

Ligne 5 : Il s'agit de l'indication 'rb' : r pour read et b pour byte.

Ligne 8 : il s'agit simplement de pouvoir rentrer une première fois dans la boucle non bornée while.

En comptant manuellement, on voit que le fichier est composé de 17 octets.

L'affichage des bytes est pratique une fois qu'on a l'habitude mais ne permet pas de voir clairement que ce sont juste des octets. Nouveau programme : on affiche le contenu trois fois de suite :

  • Une première fois en les affichant avec le principe de Python.
  • Une deuxième fois en obtenant leurs valeurs en base 10
  • Une troisième fois en affichant leurs valeurs en base 16

Les seules différences entre les trois tient dans la façon d'afficher l'octet donc.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
# Création et fermeture du fichier fichier = open('lecture.txt', 'w', encoding="iso8859_15") fichier.write("Dernière partie.\n") fichier.close() # Ouverture du fichier en mode byte fichier = open('lecture.txt', 'br') # Affichage en utilisant l'affichage standard des bytes en Python octet = b'0' while octet : position = fichier.tell() # On mesure la position du pointeur de lecture octet = fichier.read(1) # On lit un octet dans le flux if octet : print(f"Position dans le fichier {position}. Lecture : ", octet) # Affichage en affichant les valeurs décimales octet = b'0' while octet : position = fichier.tell() # On mesure la position du pointeur de lecture octet = fichier.read(1) if octet : print(f"Position dans le fichier {position}. Lecture : ", octet[0]) # Affichage en affichant les valeurs hexadécimales octet = b'0' while octet : position = fichier.tell() # On mesure la position du pointeur de lecture octet = fichier.read(1) if octet : print(f"Position dans le fichier {position}. Lecture : ", hex(octet[0])) # Fermeture du fichier fichier.close()

14° Utiliser le programme précédent.

Question

Pourquoi UN SEUL AFFICHAGE ?

...CORRECTION...

Simplement car à chaque utilisateur du read on se déplace de un octet. Au bout d'un moment, nous arrivons donc... à la fin du fichier !

Lorsqu'on arrive en ligne 21 ou 29, on est déjà en fin de fichier. La lecture ne renvoit donc rien.

Comment faire alors ? Il faut revenir en arrière. Pour cela, il existe une méthode nommée seek. On lui transmet en argument la position à laquelle on veut placer le pointeur de fichier.

Ici, on veut le remettre à zéro, revenir au début du fichier.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
# Création et fermeture du fichier fichier = open('lecture.txt', 'w', encoding="iso8859_15") fichier.write("Dernière partie.\n") fichier.close() # Ouverture du fichier en mode byte fichier = open('lecture.txt', 'br') # Affichage en utilisant l'affichage standard des bytes en Python octet = b'0' while octet : position = fichier.tell() # On mesure la position du pointeur de lecture octet = fichier.read(1) # On lit un octet dans le flux if octet : print(f"Position dans le fichier {position}. Lecture : ", octet) # Affichage en affichant les valeurs décimales fichier.seek(0) octet = b'0' while octet : position = fichier.tell() # On mesure la position du pointeur de lecture octet = fichier.read(1) if octet : print(f"Position dans le fichier {position}. Lecture : ", octet[0]) # Affichage en affichant les valeurs hexadécimales fichier.seek(0) octet = b'0' while octet : position = fichier.tell() # On mesure la position du pointeur de lecture octet = fichier.read(1) if octet : print(f"Position dans le fichier {position}. Lecture : ", hex(octet[0])) # Fermeture du fichier fichier.close()

15° Utiliser le nouveau programme. Vous devriez cette fois obtenir trois fois le contenu du fichier.

Position dans le fichier 0. Lecture : b'D' Position dans le fichier 1. Lecture : b'e' Position dans le fichier 2. Lecture : b'r' Position dans le fichier 3. Lecture : b'n' Position dans le fichier 4. Lecture : b'i' Position dans le fichier 5. Lecture : b'\xe8' Position dans le fichier 6. Lecture : b'r' Position dans le fichier 7. Lecture : b'e' Position dans le fichier 8. Lecture : b' ' Position dans le fichier 9. Lecture : b'p' Position dans le fichier 10. Lecture : b'a' Position dans le fichier 11. Lecture : b'r' Position dans le fichier 12. Lecture : b't' Position dans le fichier 13. Lecture : b'i' Position dans le fichier 14. Lecture : b'e' Position dans le fichier 15. Lecture : b'.' Position dans le fichier 16. Lecture : b'\n'
Position dans le fichier 0. Lecture : 68 Position dans le fichier 1. Lecture : 101 Position dans le fichier 2. Lecture : 114 Position dans le fichier 3. Lecture : 110 Position dans le fichier 4. Lecture : 105 Position dans le fichier 5. Lecture : 232 Position dans le fichier 6. Lecture : 114 Position dans le fichier 7. Lecture : 101 Position dans le fichier 8. Lecture : 32 Position dans le fichier 9. Lecture : 112 Position dans le fichier 10. Lecture : 97 Position dans le fichier 11. Lecture : 114 Position dans le fichier 12. Lecture : 116 Position dans le fichier 13. Lecture : 105 Position dans le fichier 14. Lecture : 101 Position dans le fichier 15. Lecture : 46 Position dans le fichier 16. Lecture : 10
Position dans le fichier 0. Lecture : 0x44 Position dans le fichier 1. Lecture : 0x65 Position dans le fichier 2. Lecture : 0x72 Position dans le fichier 3. Lecture : 0x6e Position dans le fichier 4. Lecture : 0x69 Position dans le fichier 5. Lecture : 0xe8 Position dans le fichier 6. Lecture : 0x72 Position dans le fichier 7. Lecture : 0x65 Position dans le fichier 8. Lecture : 0x20 Position dans le fichier 9. Lecture : 0x70 Position dans le fichier 10. Lecture : 0x61 Position dans le fichier 11. Lecture : 0x72 Position dans le fichier 12. Lecture : 0x74 Position dans le fichier 13. Lecture : 0x69 Position dans le fichier 14. Lecture : 0x65 Position dans le fichier 15. Lecture : 0x2e Position dans le fichier 16. Lecture : 0xa

Regardons maintenant la différence entre un fichier encodant un texte en utilisant un table 1 octet et un fichier encodant un texte en UFT-8.

16° Utiliser ce nouveau programme. Changer ensuite l'encodage initial pour de l'utf-8. Pourquoi le fichier en UTF-8 prend-t-il plus de place en mémoire ?

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
# Création et fermeture du fichier fichier = open('lecture.txt', 'w', encoding="iso8859_15") fichier.write("Dernière partie.\n") fichier.close() # Ouverture du fichier en mode byte fichier = open('lecture.txt', 'br') # Affichage en affichant les valeurs décimales octet = b'0' while octet : position = fichier.tell() # On mesure la position du pointeur de lecture octet = fichier.read(1) if octet : print(octet[0], end=" ") # Fermeture du fichier fichier.close()

...CORRECTION...

Avec la table sur un octet "iso8859_15" :

68 101 114 110 105 232 114 101 32 112 97 114 116 105 101 46 10

Avec la table sur un octet "utf-8" :

68 101 114 110 105 195 168 114 101 32 112 97 114 116 105 101 46 10

On a donc 17 octets contre 18 octets en UTF-8.

L'augmentation de taille vient des caractères non-ASCII (ici le é) qui en UTF-8 occupent 2, 3 ou 4 octets pour les plus rares.

Un fichier n'est donc qu'une suite d'octets.

Fichier texte : suite d'octets.

Fichier image : suite d'octets.

Fichier exécutable : suite d'octets.

Dernier point : cette partie n'était destinée qu'à vous montrer le principe des fichiers. Pour les fichiers-texte, la lecture ligne par ligne est facilité par l'utilisation de la méthode readline associée à une boucle FOR. C'est bien cela qu'il faut savoir utiliser.

1 2 3 4 5 6 7 8 9 10
# 1 - Création de l'objet-fichier : ouverture en mode w obj_fichier = open('aaa.txt', 'r', encoding="utf-8") print(type(obj_fichier)) # 2 - Remplissage progressif du fichier for ligne in obj_fichier : print(ligne, end="") # 3 - Fermeture de l'objet-fichier obj_fichier.close()

Si vous comprenez maintenant sans problème le code précédent, vous avez acquis ce qu'il faut sur le thème.

5 - FAQ

J'ai vu plein de programmes sur le net où on ne donne pas l'encodage.

Si on ne note pas d'encodage, l'interpréteur va le choisir pour vous !

Les versions actuelles de Python sont définies avec utf-8 comme encodage par défaut.

Noter l'encodage ne fait jamais de mal, surtout quand on débute. Cela vous permet de vous souvenir qu'on a juste des octets auxquels on donne un sens en utilisant une technique d'encodage.

J'ai vu des programmes avant des with. C'est quoi ?

Le problème du fichier ? Il faut l'ouvrir et penser à le fermer. Or, parfois, une interruption du programme peut empêcher d'atteindre l'instruction de fermeture.

Dans ce cas, il arrive parfois qu'on ne parvienne plus à ouvrir le fichier car le système pense qu'il est encore ouvert. Ou alors une modification n'a pas pu être faite correctement et le fichier est corrompu (c'est à dire qu'on ne parvient plus à décoder son contenu correctement).

Pour contourner le problème, Python propose un gestionnaire de contexte, context manager en anglais. Et son utilisation se fait en utilisant le mot-clé with.

Le principe est simple : en l'utilisant à l'ouverture, l'interpréteur s'arrange pour fermer le fichier dans tous les cas. Ce n'est pas vous qui avez à placer votre méthode close. Il s'en charge tout seul.

Voici un exemple d'utilisation :

1 2
with open('lecture.txt', 'w', encoding="utf-8") as fichier : fichier.write("Dernière partie.\n")

On voit donc qu'on utilise pas d'affectation directe. On utilise les mots-clé with et as pour faire le lien entre la variable fichier et l'instruction qui a permi de la créer open('lecture.txt', 'w', encoding="utf-8").

On retrouve le : et l'indentation. Dès qu'on sort de l'indentation, c'est qu'on ferme le fichier, automatiquement. C'est l'interpréteur qui s'en charge.

Autre exemple, en lecture :

1 2 3 4 5 6
with open('lecture.txt', 'br') as fichier : octet = b'0' while octet : octet = fichier.read(1) if octet : print(octet[0], end=" ")

Si nous savons créer des formulaires HTML, si nous savez récupérer les requêtes associées sur un serveur et enregistrer les résultats dans un fichier, nous allons être capables de créer une vraie première application Web assez complexe. C'est le but de la prochaine activité sur le thème du Web.

Activité publiée le 24 06 2020
Dernière modification : 24 06 2020
Auteur : ows. h.