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 ? Comment enregistrer un dictionnaire par exemple...
01° Voici un script permettant de créer un fichier texte. Suivre les instructions et questions décrites ci-dessous.
Créer un répertoire qu'on nommera activiteFichier.
Enregistrer ce script de le répertoire 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 fichierobj_fichier.write("Premier contenu")obj_fichier.write("Deuxième ajout")# 3 - Fermeture de l'objet-fichierobj_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
Pourquoi le fichier est-il créé dans le même répertoire que le fichier Python ?
...CORRECTION...
Tout simplement car on ne donne que le nom du fichier à créer.
Il s'agit donc d'une adresse relative, relative à l'endroit où se trouve le fichier Python.
Relative à l'endroit où se situe le fichier contenant l'appel à open(). Le fichier texte est donc créé dans le même répertoire que celui du programme.
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 : elle écrit des octets dans le fichier. Si on ne signale pas qu'il faut insérer l'octet signalant le passage à la ligne, la méthode ne le rajoute pas automatiquement. Elle fait simplement ce qu'on lui demande.
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.
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.
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 fichierobj_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-fichierobj_fichier.close()
Question
Qu'est devenu l'ancien contenu ?
...CORRECTION...
Voici le contenu :
Voici une nouvelle ligne↲
Cette fois, c'est la dernière ligne du fichier.↲
Chose surprenante : le nouveau contenu a supprimé le premier contenu !
Alors comment faire pour rajouter du contenu sans supprimer l'ancien ?
1.1 Créer un fichier-texte avec la fonction open()
Création avec open()
Pour écrire dans un fichier-texte, il faut commencer par l'ouvrir avec la fonction open() : cette fonction permet de créer un objet-fichier dont on va pouvoir utiliser la référence pour interagir avec le vrai contenu en mémoire.
Open avec l'option "w", le mode write (écrasement)
1
obj_fichier=open('aaa.txt','w',encoding="utf-8")
Cela crée l'objet-fichier obj_fichier mais en supprimant tout le contenu éventuel précédent.
On utilise ce mode lorsqu'on veut créer un nouveau contenu.
Open avec l'option "a", le mode append (rajout)
1
obj_fichier=open('aaa.txt','a',encoding="utf-8")
Cela crée l'objet-fichier obj_fichier mais en récupérant l'ancien contenu s'il existe.
Comme pour les tableaux dynamiques (type list en Python), "append" veut dire qu'on rajoute le contenu à la fin du contenu précédent.
On utilise ce mode lorsqu'on veut rajouter du contenu sans perdre l'ancienne information.
1.2 Rajout de contenu avec la méthode write()
On utilise la notation avec le point qu'on utilise sur les objets : fichier-objet.méthode().
Ceci ajoute le texte "Bonjour" dans l'objetfichier MAIS sans passer à la ligne, ni avant, ni après.
2
obj_fichier.write("Bonjour")
Si vous voulez ajouter un passage à la ligne, il faudra l'indiquer à l'aide de la présence du caractère \n dans la chaîne.
2
obj_fichier.write("Voici une nouvelle ligne\n")
1.3 Fermeture de l'objet-fichier avec la méthode close()
3
obj_fichier.close()
Attention : si la fermeture est mal effectuée, ou pas effectuée, cela peut entrainer des problèmes lors d'une prochaine ouverture. Pensez donc bien à fermer votre objet.
04° Créer un script qui permet cette fois de rajouter deux lignes au fichier 'aaa.txt' sans pour autant supprimer le texte déjà enregistré.
...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 fichierobj_fichier.write("Et cette fois, on supprime ou pas ?\n")obj_fichier.write("Ah ben non. On rajoute.\n")# 3 - Fermeture de l'objet-fichierobj_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.
1.4 Exemple d'écriture dans un fichier
Exemple où on remplace intégralement le contenu d'un fichier.
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 fichierobj_fichier.write("Premier contenu")obj_fichier.write("Deuxième ajout")# 3 - Fermeture de l'objet-fichierobj_fichier.close()
Exemple où on rajoute à la fin du fichier, sans écraser l'ancien contenu.
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','a',encoding="utf-8")# 2 - Remplissage progressif du fichierobj_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-fichierobj_fichier.close()
Saut à la ligne avec Windows
La lecture d'un fichier-texte issu de Windows montre parfois la présence d'un caractère particulier en plus de \n : le caractère d'échappement retour-chariot \r (octet contenant 13 en ASCII).
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.
Nous allons voir :
Comment lire une ligne à la fois avec readline()
Comment lire toutes les lignes readline() dans une boucle TANT QUE
Comment lire toutes les lignes readline() dans une boucle POUR
Comment lire un caractère à la fois avec read()
Comment gérer l'encodage utilisé sur le fichier-texte
2.1 Lecture manuelle d'une ligne avec la méthode readline()
Lorsqu'on ouvre un fichier-objet, Python génère une tête de lecture qui pointe initialement au début du fichier-texte.
La méthode readline() renvoie un string contenant la prochaine ligne qu'on peut lire à partir de la position actuelle de la tête de lecture du fichier-objet. Elle renvoie dans le string situé entre
La tête de lecture
Le prochain \n (Line Feed, 10 en ASCII) ou la fin du fichier (EOF, End Of File)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 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 fichiera=obj_fichier.readline()print(a,end="")b=obj_fichier.readline()print(b,end="")c=obj_fichier.readline()print(c,end="")d=obj_fichier.readline()print(d,end="")# 3 - Fermeture de l'objet-fichierobj_fichier.close()
Voici un exemple de résultat :
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.
Ici, chaque ligne sera simplement affichée sur la console à l'aide de la fonction native print(). Pourquoi avoir rajouté end="" ?
Tout simplement car le \n fait partie du string renvoyé. Si vous ne modifiez pas la fin du print(), vous aurez deux passages à la ligne : celui à l'intérieur du string et celui généré par défaut par print().
>>> a
'Voici une nouvelle ligne\n'>>> b
'Cette fois, c'est la dernière ligne du fichier.\n'>>> c
'Et cette fois, on supprime ou pas ?\n'>>> c
'Ah ben non. On rajoute.\n'
05° Utiliser le script suivant puis rajouter quelques autres lectures de façon à tenter de lire plus de lignes que le fichier n'en possède.
Questions
Quel est le string qu'on récupère lorsqu'on lit alors qu'on se trouve à la fin du fichier ?
Python déclenche-t-il une erreur lorsqu'on va 'trop loin' ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 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 fichiera=obj_fichier.readline()print(a,end="")b=obj_fichier.readline()print(b,end="")c=obj_fichier.readline()print(c,end="")d=obj_fichier.readline()print(d,end="")# 3 - Fermeture de l'objet-fichierobj_fichier.close()
...CORRECTION...
La fin de fichier est représenté par un string vide "".
Une fois en fin de fichier, on peut tenter de lire autant de lignes qu'on veut, on n'obtient pas une erreur mais on lit simplement encore et encore un string vide "".
Avec cette façon de faire, si on a 1500 lignes, on est parti pour taper 1500 fois readline()...
Heureusement, notre objet-fichier obj_fichier est un itérable : on peut utiliser une boucle FOR pour lire ses éléments un par un.
Je présente ci-dessous deux manières de lire toutes les lignes d'un fichier-texte en utilisant une boucle.
2.2 Boucle while avec la méthode readline()
Principe
On lit et enregistre une première ligne
TANT QUE la ligne n'est pas vide
On fait le traitement de cette ligne
On lit et enregistre la ligne suivante
Fin du TANT QUE
Il faudra donc veiller à initialiser la variable de boucle avec quelque chose qui permette de rentrer une première fois dans la boucle.
Exemple
1
2
3
4
5
6
7
8
9
10
11
12
# 1 - Création de l'objet-fichier : ouverture en mode r (read)obj_fichier=open('aaa.txt','r',encoding="utf-8")# 2 - Lecture ligne par ligneligne=obj_fichier.readline()whileligne!="":print(ligne,end="")# Traitement de la ligne actuelleligne=obj_fichier.readline()# Lecture et stockage de la ligne suivante# 3 - Fermeture de l'objet-fichierobj_fichier.close()
06° Utiliser ce script de lecture : il va vous permettre de lire et afficher en boucle les "lignes" du fichier.
1
2
3
4
5
6
7
8
9
10
11
12
# 1 - Création de l'objet-fichier : ouverture en mode r (read)obj_fichier=open('aaa.txt','r',encoding="utf-8")# 2 - Lecture ligne par ligneligne=obj_fichier.readline()whileligne!="":print(ligne,end="")ligne=obj_fichier.readline()# 3 - Fermeture de l'objet-fichierobj_fichier.close()
Questions
Quelles sont les 3 lignes qui appartiennent au TANT QUE ?
L7 : Tant qu'on n'a pas atteint la fin du fichier.
L8 : Afficher cette ligne (sans rajouter de passage à la ligne, il est intégré dans le string de la ligne)
L9 : lire et stocker la ligne suivante.
La ligne 5 permet simplement de créer une première ligne à lire. Si elle n'est pas vide, on réalisera donc la boucle. Si elle est vide dès le départ, on ne réalisera même pas un tour de boucle.
07° Tester cette nouvelle version. La seule différence se trouve en ligne 7.
Question
Que signifie la nouvelle condition ?
1
2
3
4
5
6
7
8
9
10
11
12
# 1 - Création de l'objet-fichier : ouverture en mode r (read)obj_fichier=open('aaa.txt','r',encoding="utf-8")# 2 - Lecture ligne par ligneligne=obj_fichier.readline()whileligne:print(ligne,end="")# Traitement de la ligne actuelleligne=obj_fichier.readline()# Lecture et stockage de la ligne suivante# 3 - Fermeture de l'objet-fichierobj_fichier.close()
...CORRECTION...
L'interpréteur Python interprète l'expression derrière le while comme un booléen, même si cette expression ne l'est pas.
Il suffit de se souvenir qu'en Python :
False, c'est tout ce qui est nul ou vide.
True, c'est... tout le reste.
La condition de poursuite veut donc dire de continuer si ligne contient autre chose que 0, False, None, une chaîne vide ou un tableau non vide, ou un dictionnaire non vide ou un tuple non vide...
Puisque ligne est un string, cela veut donc dire de continuer TANT QUE la ligne contient quelque chose.
2.3 Boucle while avec la méthode readline() V2
Evaluer un non-booléen en booléen en Python
!!! A SAVOIR PAR COEUR !!!
En Python, un contenu VIDE ou NUL est évalué à False si on demande un résulat booléen.
Dans tous les autres cas, le résultat est True.
Conséquence sur la condition de poursuite
On obtient donc un code encore plus simple que le précédent :
1
2
3
4
5
6
7
8
9
10
11
12
# 1 - Création de l'objet-fichier : ouverture en mode r (read)obj_fichier=open('aaa.txt','r',encoding="utf-8")# 2 - Lecture ligne par ligneligne=obj_fichier.readline()whileligne:print(ligne,end="")# Traitement de la ligne actuelleligne=obj_fichier.readline()# Lecture et stockage de la ligne suivante# 3 - Fermeture de l'objet-fichierobj_fichier.close()
L'objet-fichier est un itérable en Python : nous allons donc pouvoir utiliser un POUR.
2.4 Boucle for avec la méthode readline()
Principe
On lit l'une des lignes à chaque tour de boucle
Et c'est tout.
C'est comme lire une à une les valeurs d'un tableau.
Ici, on lit une à une les lignes du fichier.
Exemple
1
2
3
4
5
6
7
8
9
# 1 - Création de l'objet-fichier : ouverture en mode wobj_fichier=open('aaa.txt','r',encoding="utf-8")# 2 - Remplissage progressif du fichierforligneinobj_fichier:print(ligne,end="")# 3 - Fermeture de l'objet-fichierobj_fichier.close()
Le plus explicite est donc de nommer la variable de boucle ligne plutôt que k, x ou autre, puisqu'elle va contenir l'une des lignes, une par tour de boucle.
08° Utiliser ce script de lecture : il va vous permettre de lire et afficher en boucle les "lignes" du fichier.
En ligne 2, on notera qu'on demande le type de l'objet-fichier obj_fichier.
Question : 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 wobj_fichier=open('aaa.txt','r',encoding="utf-8")print(type(obj_fichier))# 2 - Remplissage progressif du fichierforligneinobj_fichier:print(ligne,end="")# 3 - Fermeture de l'objet-fichierobj_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).
On peut également 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 passage à la ligne /n.
2.5 Lire un caractère à la fois avec la méthode read()
Principe
La méthode read() lit le flux de données en fonction d'un nombre de caractères plutôt que d'aller nécessairement jusqu'au prochain passage à la ligne /n.
On lui fournit en argument le nombre de caractères à lire. Si on ne précise pas d'argument, la méthode va renvoyer... la totalité du flux.
Exemple
Voici un script de lecture qui vous permettra de lire les caractères enregistrés dans le fichier un par un. On affiche chaque caractère, à part les a ou 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.
10
print(lecture,end="*")
Voici le script :
1
2
3
4
5
6
7
8
9
10
11
12
13
# 1 - Création de l'objet-fichier : ouverture en mode wobj_fichier=open('aaa.txt','r',encoding="utf-8")# 2 - Remplissage progressif du fichierlecture="o"# Affectation quelconque pour rentrer une première fois dans la bouclewhilelecture:lecture=obj_fichier.read(1)iflecture=='a'orlecture=='A':lecture='@'print(lecture,end="*")# 3 - Fermeture de l'objet-fichierobj_fichier.close()
09° Utiliser le script présenté ci-dessus et visualiser le résultat.
Questions
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 fournisse des blocs de 5 caractères à la fois.
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. Ici, on constate donc qu'il y a une étoile en début de chaque nouvelle ligne. 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). Il faudrait donc le lire en décodant le fichier en UTF-8 également.
✎ 10° Lire et utiliser le script suivant qui
crée un fichier en UTF-8 puis le ferme (sur les lignes 2-3-4)
lit ce fichier en UFT-8 puis le ferme (sur les lignes 7-8-9-10).
1
2
3
4
5
6
7
8
9
10
# 1 - Ecriture du fichierobj_fichier=open('perceval.txt','w',encoding="utf-8")obj_fichier.write("C'est écrit en UTF-8 ?\nDe toutes manières, j'ai jamais rien compris à vos histoires d'encodage.")obj_fichier.close()# 2 - lecture du fichierobj_fichier=open('perceval.txt','r',encoding="utf-8")forligneinobj_fichier:print(ligne)obj_fichier.close()
Questions
Modifier le fichier pour le créer en UTF-8 mais en le lisant en iso8859_15 (également nommée latin9 ou latin-9). Il s'agit de la table ASCII étendu (un octet) pour l'europe de l'Ouest. Fournir le code du nouveau script sur votre copie.
Que constatez-vous lorsqu'on tente de lire un fichier en n'utilisant pas l'encodage utilisé pour le créer ?
Ci-dessous le script initial et le résultat attendu avant et après modification.
Affichage avec écriture en UTF-8 et lecture en UTF-8 :
C'est écrit en UTF-8 ?
De toutes manières, j'ai jamais rien compris à vos histoires d'encodage.
Affichage avec écriture en UTF-8 et lecture en iso8859_15 :
✎ 11° Créer un script qui permet de créer un fichier-texte contenant le texte suivant en l'encodant en iso8859_15.
texte = "Ce court texte a été créé en considérant le fait qu'on a besoin de caractères peu courants lorsqu'on veut comparer les tailles obtenues avec différents encodages, à savoir le fait que la plus petite taille sera obtenue avec les tables 1 octet et la plus grande taille avec utf-32"
Vérifier que la texte du fichier-texte est de 279 octets.
Ouvrir le fichier en cliquant dessous pour vérifier qu'il contient bien le bon texte.
✎ 12° Modifier le script de façon à créer le même fichier-texte mais en utilisant différents encodages.
Questions
Quelle est la taille du fichier-texte encodé en utf-8 ?
Quelle est la taille du fichier-texte encodé en utf-16 ?
Quelle est la taille du fichier-texte encodé en utf-32 ?
Taille des fichiers-texte
Les fichiers-texte encodés en ASCII étendu pèsent un octet par caractère.
Les fichiers-texte encodés en UTF-8 pèsent à peine plus si les caractères sont principalement des fichiers ASCII.
Les fichiers-texte encodés en UTF-16 pèsent deux fois plus environ.
Les fichiers-texte encodés en UTF-32 pèsent quatre fois plus que le fichier en ASCII étendu.
rajouter des choses dans les fichiers (avec 'a') et
lire les fichiers avec (avec 'r')
Une fois lu dans Python, ces textes se retrouvent stocker dans des strings. Il est donc important de connaître quelques manipulations basiques avec des strings.
Rappel : actions et tests sur les strings
Quelques rappels sur des actions assez pratiques.
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.
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"
Récupérer les caractères dans un tableau
Il suffit d'utiliser la fonction native list().
>>> nom = "Merlin ou Toto l'asticot"
>>> t = list(nom)
>>> t
['M', 'e', 'r', 'l', 'i', 'n', ' ', 'o', 'u', ' ', 'T', 'o', 't', 'o', ' ', 'l', "'", 'a', 's', 't', 'i', 'c', 'o', 't']
Récupérer les mots d'une phrase
Facile en Python : il suffit d'utiliser la méthode split() en précisant que le caractère de séparation est l'espace.
>>> nom = "Merlin ou Toto l'asticot"
>>> t = nom.split(' ')
>>> t
['Merlin', 'ou', 'Toto', "l'asticot"]
Récupérer les informations dans une ligne d'un fichier CSV
Dans un fichier CSV, chaque enregistrement consiste en une ligne. Sur cette ligne, les informations sont séparées par des virgules ou des points-virgules.
Pour les séparer, il suffit d'utiliser la méthode split() en précisant que le caractère de séparation est le point-virgule par exemple.
>>> ligne = "Merlin;magicien;999 ans;Forêt de Brocéliande/n"
>>> t = ligne.split(';')
>>> t
['Merlin', 'magicien', '999 ans', 'Forêt de Brocéliande/n']
Transformer un caractère en un autre
Pratique par exemple pour supprimer les /n reçus dans un string.
>>> ligne = "Merlin;magicien;999 ans;Forêt de Brocéliande/n"
>>> ligne_bis = ligne.replace("/n", "")
>>> t = ligne_bis.split(";")
>>> t
['Merlin', 'magicien', '999 ans', 'Forêt de Brocéliande']
Si vous voulez voir les autres méthodes, vous pouvez aller voir cette fiche ou faire des recherches sur le Web :
✎ 13° 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 ?
fichier=open('musique.csv','a',encoding='utf-8')continuer="o"whilecontinuer.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()
✎ 14° 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é, comateux.
On demande d'enregistrer des choses. C'est fait. Mais comment les lire ?
✎ 15° 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.
Cette partie va aller vite. Non pas car c'est simple mais parce qu'il y a trop à dire !.
Les expressions régulières sont un moyen de trouver des motifs dans un string.
Il faut fournir entre crochets l'ensemble des caractères qu'on recherche.
[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.
[0-9]{2} veut dire qu'on s'attend à trouver deux chiffres : 08, 75 ou 42 sont valides mais pas 7A.
([0-9]{2}-) signale avec les parenthèses la recherche d'une séquence composée de deux chiffres suivi d'un tiret : 78- ou 12- ou 06- mais pas Av!.
Un exemple pour la recherche d'un numéro de téléphone dans un texte. Avec Python, il faut utiliser le module re.
>>> import re
>>> texte = "Le numéro de Toto l'asticot est 06-07-06-07-06..."
>>> sequence = "([0-9]{2}-){4}([0-9]{2}){1}"
On recherche donc 4 séquences chiffre chiffre tiret suivi d'une unique séquence chiffre chiffre.
>>> 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 n°')
Ce texte contient un n°>>> 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.
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.
✎ 16° Tenter de créer un test sur la date pour ne pas enregistrer la demande si la date ne respecte pas ce format : une séquence de 2 chiffres suivi d'un tiret, puis une séquence de 4 chiffres.
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.
17° 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 fichierfichier=open('lecture.txt','w',encoding="iso8859_15")fichier.write("Dernière partie.\n")fichier.close()# Ouverture du fichier en mode bytefichier=open('lecture.txt','br')# Affichage en utilisant l'affichage standard des bytes en Pythonoctet=b'0'whileoctet:position=fichier.tell()# On mesure la position du pointeur de lectureoctet=fichier.read(1)# On lit un octet dans le fluxifoctet:print(f"Position dans le fichier {position}. Lecture : ",octet)# Fermeture du fichierfichier.close()
Questions
Ligne 5 : Qu'est-ce qui montre qu'on ouvre le fichier en mode binaire et pas en mode texte ?
Ligne 8 : pourquoi créer une variable octet à cette endroit pour y mettre "n'importe quoi" ?
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.
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'
L'affichage des bytes de cette façon 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.
# Création et fermeture du fichierfichier=open('lecture.txt','w',encoding="iso8859_15")fichier.write("Dernière partie.\n")fichier.close()# Ouverture du fichier en mode bytefichier=open('lecture.txt','br')# Affichage en utilisant l'affichage standard des bytes en Pythonoctet=b'0'whileoctet:position=fichier.tell()# On mesure la position du pointeur de lectureoctet=fichier.read(1)# On lit un octet dans le fluxifoctet:print(f"Position dans le fichier {position}. Lecture : ",octet)# Affichage en affichant les valeurs décimalesoctet=b'0'whileoctet:position=fichier.tell()# On mesure la position du pointeur de lecture octet=fichier.read(1)ifoctet:print(f"Position dans le fichier {position}. Lecture : ",octet[0])# Affichage en affichant les valeurs hexadécimalesoctet=b'0'whileoctet:position=fichier.tell()# On mesure la position du pointeur de lectureoctet=fichier.read(1)ifoctet:print(f"Position dans le fichier {position}. Lecture : ",hex(octet[0]))# Fermeture du fichierfichier.close()
18° 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.
# Création et fermeture du fichierfichier=open('lecture.txt','w',encoding="iso8859_15")fichier.write("Dernière partie.\n")fichier.close()# Ouverture du fichier en mode bytefichier=open('lecture.txt','br')# Affichage en utilisant l'affichage standard des bytes en Pythonoctet=b'0'whileoctet:position=fichier.tell()# On mesure la position du pointeur de lectureoctet=fichier.read(1)# On lit un octet dans le fluxifoctet:print(f"Position dans le fichier {position}. Lecture : ",octet)# Affichage en affichant les valeurs décimalesfichier.seek(0)octet=b'0'whileoctet:position=fichier.tell()# On mesure la position du pointeur de lecture octet=fichier.read(1)ifoctet:print(f"Position dans le fichier {position}. Lecture : ",octet[0])# Affichage en affichant les valeurs hexadécimalesfichier.seek(0)octet=b'0'whileoctet:position=fichier.tell()# On mesure la position du pointeur de lectureoctet=fichier.read(1)ifoctet:print(f"Position dans le fichier {position}. Lecture : ",hex(octet[0]))# Fermeture du fichierfichier.close()
19° 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.
20° 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 fichierfichier=open('lecture.txt','w',encoding="iso8859_15")fichier.write("Dernière partie.\n")fichier.close()# Ouverture du fichier en mode bytefichier=open('lecture.txt','br')# Affichage en affichant les valeurs décimalesoctet=b'0'whileoctet:position=fichier.tell()# On mesure la position du pointeur de lecture octet=fichier.read(1)ifoctet:print(octet[0],end=" ")# Fermeture du fichierfichier.close()
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.
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.