Les fichiers

    Publicités

Users Who Are Viewing This Thread (Total: 0, Members: 0, Guests: 0)

Superman

V
Ancien staff
Dec 2, 2009
2,489
0
596
Avant de commencer

Nous allons beaucoup travailler sur des répertoires et des fichiers, autrement dit sur votre disque. Donc je vais vous donner quelques informations générales avant de commencer, pour que malgré vos différents systèmes et configurations, vous puissiez essayer les instructions que je vais vous montrer
smile.png
.

Mais d'abord pourquoi lire ou écrire dans des fichiers ?


Peut-être que vous ne voyez pas trop l'intérêt de savoir lire et écrire dans des fichiers, hors quelques applications de temps à autre. Mais souvenez-vous que, quand vous fermez votre programme, aucune de vos variables n'est sauvegardée. Or, les fichiers peuvent être, justement, un excellent moyen de garder les valeurs de certains objets pour pouvoir les récupérer quand vous rouvrirez votre programme. Par exemple, un petit jeu peut enregistrer les scores des joueurs.

Si dans notre TP ZCasino nous avions pu enregistrer, au moment de quitter le casino, la somme que nous avions en poche, nous aurions pu rejouer sans repartir de zéro.

Changer le répertoire de travail courant


Si vous souhaitez travailler dans l'interpréteur Python, et je vous y encourage, vous devrez changer le répertoire de travail courant. En effet, au lancement de l'interpréteur, le répertoire de travail courant est celui dans lequel se trouve l'exécutable de l'interpréteur. Sous Windows, c'est "C:\Python3X", le X étant différent en fonction de votre version de Python. Dans tous les cas, je vous invite à changer de répertoire de travail courant. Pour cela, vous devez utiliser une fonction du module os, qui s'appelle chdir (Change Directory).

Code : Python Console1
2
3
>>> import os
>>> os.chdir("C:/tests python")
>>>




Le répertoire doit exister. Modifier la chaîne passée en paramètre de os.chdir en fonction du dossier dans lequel vous souhaitez vous déplacer.

Je vous conseille, que vous soyez sous Windows ou non, d'utiliser le symbole / pour décrire un chemin.


Vous pouvez utiliser, en le doublant, l'antislash \\ mais si vous oubliez de le doubler, vous aurez des erreurs. Je vous conseille donc d'utiliser le slash /, cela marche très bien même sous Windows.

N.B. : quand vous lancez un programme Python directement, en double-cliquant dessus par exemple, le répertoire courant est celui où vous lancez le programme. Si vous avez un fichier mon_programme.py contenu sur le disque C:, le répertoire de travail courant quand vous lancerez le programme sera C:\.

Chemins relatifs et absolus


Pour décrire l'arborescence d'un système, on a deux possibilités :


  • Les chemins absolus
  • Les chemins relatifs


Le chemin absolu


Quand on décrit une cible (un fichier ou un répertoire) sous la forme d'un chemin absolu, on décrit la suite des répertoires menant au fichier. Sous Windows, on partira du nom de volume (C:\, D:\...). Sous les systèmes Unix, ce sera plus vraissemblablement depuis /.

Par exemple, sous Windows, si on a un fichier nommé fic.txt, contenu dans un dossier test, lui-même présent sur le disque C:, notre chemin absolu menant à notre fichier sera C:\test\fic.txt.

Le chemin relatif


Quand on décrit la position d'un fichier grâce à un chemin relatif, cela veut dire que l'on tient compte du dossier dans lequel on se trouve actuellement. Ainsi, si on se trouve dans le dossier C:\test et que l'on souhaite accéder au fichier fic.txt contenu dans ce même dossier, le chemin relatif menant à ce fichier sera tout simplement fic.txt.

Maintenant, si on se trouve dans C:, notre chemin relatif sera test\fic.txt.

Quand on décrit un chemin relatif, on utilise parfois le symbole .. qui désigne le répertoire parent. Voici un nouvel exemple :


  • C:
    • test
      • rep1
        • fic1.txt
      • rep2
        • fic2.txt
        • fic3.txt


C'est dans notre dossier test que tout se passe. Nous avons deux sous-répertoires nommés rep1 et rep2. Dans rep1, nous avons un seul fichier : fic1.txt. Dans rep2, nous avons deux fichiers : fic2.txt et fic3.txt.

Si le répertoire de travail courant est rep2 et que l'on souhaite accéder à fic1.txt, notre chemin relatif sera donc ..\rep1\fic1.txt.

N.B. : j'utilise ici des anti-slash parce que l'exemple d'arborescence est un modèle Windows et que ce sont les séparateurs utilisés pour décrire une arborescence Windows. Mais dans votre code je vous conseille quand même d'utiliser un slash (/).

Résumé


Les chemins absolus et relatifs sont donc deux moyens de décrire le chemin menant à des fichiers ou répertoires. Mais si le résultat est le même, le moyen utilisé n'est pas identique : quand on utilise un chemin absolu, on décrit toute l'arborescence menant au fichier, peu importe l'endroit où on se trouve. Un chemin absolu permet d'accéder à un endroit dans le disque peu importe le répertoire de travail courant. L'inconvénient de cette méthode, c'est qu'on doit savoir en général où se trouvent les fichiers qui nous intéressent sur le disque.

Le chemin relatif décrit l'arborescence en prenant comme point d'origine non pas la racine, ou le périphérique sur lequel est stocké la cible, mais le répertoire dans lequel on se trouve. Ça a certains avantages quand on code un projet, on est pas obligé de savoir où le projet est stocké pour construire plusieurs répertoires. Mais ce n'est pas forcément la meilleure solution en toute circonstance.

Comme je l'ai dit, quand on lance l'interpréteur Python, on a bel et bien un répertoire de travail courant. Vous pouvez l'afficher grâce à la fonction os.getcwd() (CWD = "Current Working Directory").

Cela devrait vous suffir donc. Pour les démonstrations qui vont suivre, placez-vous à l'aide de os.chdir dans un répertoire de test créé pour l'occasion.
Lecture et écriture dans un fichier

Nous allons commencer à lire avant d'écrire dans un fichier. Pour l'exemple donc, je vous invite à créer un fichier dans le répertoire de travail courant que vous avez choisi. Je suis en manque flagrant d'inspiration, je vais l'appeler fichier.txt et je vais écrire dedans, à l'aide d'un éditeur sans mise en forme (tel que le bloc-notes Windows) : « C'est le contenu du fichier. Spectaculaire non ? »

Ouverture du fichier


D'abord, il nous faut ouvrir le fichier avec Python. On utilise pour ce faire la fonction open, disponible sans avoir besoin de rien importer. Elle prend en paramètres :


  • le chemin (absolu ou relatif) menant au fichier à ouvrir ;
  • le mode d'ouverture.


Le mode est donné sous la forme d'une chaîne de caractères. Voici les principaux modes :

ModeExplications 'r' Ouverture en lecture (Read). 'w' Ouverture en écriture (Write). Le contenu du fichier est écrasé. Si le fichier n'existe pas, il est créé. 'a' Ouverture en écriture en mode ajout (Append). On écrit à la fin du fichier sans écraser l'ancien contenu du fichier. Si le fichier n'existe pas, il est créé.

On peut ajouter à tous ces modes le signe b pour ouvrir le fichier en mode binaire. Nous verrons plus loin l'utilité, c'est un mode un peu particulier.

Ici nous souhaitons lire le fichier. Nous allons donc utilisé le mode 'r'.

Code : Python Console1
2
3
4
5
6
>>> mon_fichier = open("fichier.txt", "r")
>>> mon_fichier
<_io.TextIOWrapper name='fichier.txt' encoding='cp1252'>
>>> type(mon_fichier)
<class '_io.TextIOWrapper'>
>>>




L'encodage précisé quand on affiche le fichier dans l'interpréteur peut être très différent en fonction de votre système. Ici je suis dans l'interpréteur Python dans Windows et l'encodage choisi est donc un encodage Windows propre à la console. Ne soyez pas surpris s'il est différent chez vous.

La fonction open crée donc un fichier. Elle retourne un objet issue de la classe TextIoWrapper. Par la suite, nous allons utiliser des méthodes de cette classe pour interragir avec le fichier.

Le type de l'objet doit vous surprendre quelque peu. Ça aurait très bien pu être un type file après tout. En fait, open permet d'ouvrir un fichier, mais TextIoWrapper est utilisé dans d'autres circonstances, pour afficher du texte à l'écran par exemple. Bon, ça ne nous concerne pas trop ici, je ne vais pas m'y attarder
clin.png
.

Fermer le fichier


N'oubliez pas de fermer un fichier après l'avoir ouvert. Si d'autres applications souhaitent accéder à ce fichier, ou d'autres morceaux de votre propre code, ils ne pourront pas car le fichier sera déjà ouvert. C'est surtout vrai en écriture, mais prenez de bonnes habitudes
heureux.png
. La méthode à utiliser est close :

Code : Python Console1
2
>>> mon_fichier.close()
>>>




Lire l'intégralité du fichier


Pour ce faire, on utilise la méthode read de la classe TextIoWrapper. Elle retourne l'intégralité du fichier :

Code : Python Console1
2
3
4
5
6
>>> mon_fichier = open("fichier.txt", "r")
>>> contenu = mon_fichier.read()
>>> print(contenu)
C'est le contenu du fichier. Spectaculaire non ?
>>> mon_fichier.close()
>>>




Quoi de plus simple ? La méthode read retourne tout le fichier que l'on capture dans une chaîne de caractères. Notre fichier ne contient pas de saut de ligne, mais si c'était le cas, vous auriez dans votre variable contenu les signes \n traduisant un saut de ligne.

Maintenant que vous avez une chaîne, vous pouvez naturellement tout faire : la convertir, tout entière ou en partie, si c'est nécessaire, split la chaîne pour parcourir chaque ligne et les traiter... bref, tout est possible
clin.png
.

Écriture dans un fichier


Bien entendu, il nous faut ouvrir le fichier avant tout. Vous pouvez utiliser le mode w ou le mode a. Le premier écrase le contenu éventuel du fichier, alors que le second ajoute ce que l'on écrit à la fin du fichier. À vous de voir en fonction de vos besoins
smile.png
. Dans tous les cas, ces deux modes créent le fichier s'il n'existe pas.

Écrire une chaîne


Pour écrire dans un fichier, on utilise la méthode write en lui passant en paramètre la chaîne à écrire dans le fichier. Elle retourne le nombre de caractères qui ont été écrits. On n'est naturellement pas obligé de récupérer cette valeur, sauf si on en a besoin.

Code : Python Console1
2
3
4
5
>>> mon_fichier = open("fichier.txt", "w") # argh j'ai tout écrasé !
>>> mon_fichier.write("Premier test d'écriture dans un fichier via Python")
50
>>> mon_fichier.close()
>>>




Vous pouvez vérifier que votre fichier contient bien le texte qu'on y a écrit.

Écrire d'autres types de données


La méthode write n'accepte en paramètre que des chaînes de caractères. Si vous voulez écrire dans votre fichier des nombres, des scores par exemple, il vous faudra les convertir en chaîne avant de les écrire, et les convertir en entier après les avoir lu.

Le module os contient beaucoup de fonctions intéressantes pour créer et supprimer des fichiers et des répertoires. Je vous laisse regarder l'aide si vous êtes intéressé
clin.png
.

Le mot-clé with


Ne désespérez pas, il ne nous reste plus autant de mots-clés à découvrir... mais quelques-uns tout de même. Et même certains dont je ne parlerai pas...

On n'est jamais à l'abri d'une erreur. Surtout quand on manipule des fichiers. Il peut se produire des erreurs quand on lit, quand on écrit... et si l'on n'y prend garde, le fichier restera ouvert.

Comme je vous l'ai dit, c'est plutôt gênant, et ça peut même être grave. Si votre programme souhaite de nouveau utiliser ce fichier, il ne pourra pas forcément y accéder, puisqu'il a déjà été ouvert.

Il existe un mot-clé qui permet d'éviter cette situation : with. Voici sa syntaxe :

Code : Python1
2
with open(mon_fichier, mode_ouverture) as variable:
# opérations sur le fichier




On trouve dans l'ordre :


  • Le mot-clé with, prélude au bloc dans lequel on va manipuler notre fichier. On peut trouver with dans la manipulation d'autres objets, mais nous ne le verrons pas ici
  • Notre objet. Ici, on appelle open qui va retourner un objet TextIOWraper (notre fichier)
  • Le mot-clé as que nous avons déjà vu dans le mécanisme d'importation et dans les exceptions. Il signifie toujours la même chose : "en tant que"
  • Notre variable qui contiendra notre objet. Si la variable n'existe pas, Python la créée.


Un exemple ?

Code : Python Console1
2
3
4
>>> with open('fichier.txt', 'r') as mon_fichier:
... texte = mon_fichier.read()
...
>>>




Cela ne veut pas dire que le bloc d'instructions ne lèvera aucune exception.
Cela signifie simplement que, si une exception se produit, le fichier sera tout de même fermé à la fin du bloc.

Vous pouvez appeler mon_fichier.closed pour le vérifier. Si le fichier est fermé, mon_fichier.closed vaudra True.

Il est inutile par conséquent de fermer le fichier à la fin du bloc with. Python va le faire tout seul, qu'une exception soit levée ou non. Je vous encourage à utiliser cette syntaxe, elle est plus sûre et plus facile à comprendre.

Allez ! Direction le module pickle, dans lequel nous allons apprendre à sauvegarder dans des fichiers nos objets.
Enregistrer des objets dans des fichiers

Dans beaucoup de langages de haut niveau, on peut enregistrer ses objets dans un fichier. Python ne fait pas exception. Grâce au module pickle que nous allons découvrir, on peut enregistrer n'importe quel objet et le récupérer par la suite, au prochain lancement du programme, par exemple. En outre, le fichier résultant pourra être lu depuis n'importe quel système d'exploitation (supportant Python, naturellement).

Enregistrer un objet dans un fichier


Il nous faut naturellement d'abord importer le module pickle.

Code : Python Console1
2
>>> import pickle
>>>




On va ensuite utiliser deux classes incluses dans ce module : la classe Pickler et la classe Unpickler.

C'est la première qui nous intéresse dans cette partie.

Pour créer notre objet Pickler, on va l'appeler en passant en paramètre le fichier dans lequel on va enregistrer notre objet.

Code : Python Console1
2
3
4
5
>>> with open('donnees', 'wb') as fichier:
... mon_pickler = pickle.Pickler(fichier)
... # enregistrement ...
...
>>>




Quand on va enregistrer nos objets, ce sera dans le fichier donnees. Je ne lui ai pas donné d'extension, vous pouvez le faire. Mais évitez de préciser une extension qui est utilisée par un programme.

Notez le mode d'ouverture : on ouvre le fichier donnees en mode d'écriture binaire. Il suffit de rajouter derrière le nom du mode la lettre b pour indiquer un mode binaire.

Le fichier que Python va écrire ne sera pas très lisible si vous essayez de l'ouvrir, et ce n'est pas le but
heureux.png
.

Bon. Maintenant que notre pickler est créé, on va enregistrer un ou plusieurs objets dans notre fichier. Là, c'est à vous de voir comment vous voulez vous organiser, ça dépend aussi beaucoup du projet. Moi j'ai pris l'habitude de n'enregistrer qu'un objet par fichier, mais il n'y a aucune obligation.

On utilise la méthode dump du pickler pour enregistrer notre objet. Son utilisation est des plus simples :

Code : Python Console 1
2
3
4
5
6
7
8
9
10
11
>>> score = {
... "joueur 1": 5,
... "joueur 2": 35,
... "joueur 3": 20,
... "joueur 4": 2,
>>> }
>>> with open('donnees', 'wb') as fichier:
... mon_pickler = pickle.Pickler(fichier)
... mon_pickler.dump(score)
...
>>>




Après l'exécution de ce code, vous avez dans votre dossier de test un fichier donnees qui contient... eh bien, notre dictionnaire contenant les scores de nos quatre joueurs. Si vous voulez enregistrer plusieurs objets, appelez de nouveau la méthode dump avec les objets à enregistrer. Ils seront ajoutés dans le fichier dans l'ordre où vous les enregistrez.

Récupérer nos objets enregistrés


Nous allons utiliser une autre classe définie dans notre module pickle. Cette fois, assez logiquement, c'est la classe Unpickler.

Commençons par créer notre objet. On lui passe lors de la création notre fichier dans lequel on va lire nos objets. Puisqu'on va lire, on change de mode, on repasse en mode r, et même rb puisque le fichier est binaire.

Code : Python Console1
2
3
4
5
>>> with open('donnees', 'rb') as fichier:
... mon_depickler = pickle.Unpickler(fichier)
... # lecture des objets contenus dans le fichier...
...
>>>




Pour lire l'objet dans notre fichier, il faut appeler la méthode load de notre depickler. Elle retourne le premier objet qui a été lu (s'il y en a plusieurs, il faut l'appeler plusieurs fois).

Code : Python Console1
2
3
4
5
>>> with open('donnees', 'rb') as fichier:
... mon_depickler = pickle.Unpickler(fichier)
... score_recupere = mon_depickler.load()
...
>>>




Et après cet appel, si le fichier a pu être lu, dans votre variable score_recupere, vous récupérez votre dictionnaire contenant les scores. Là, c'est peut-être peu spectaculaire, mais quand vous utilisez ce module pour sauvegarder des objets qui doivent être conservés alors que votre programme n'est pas lancé, c'est franchement très pratique
smile.png
.

Ce lien n'est pas visible, veuillez vous connecter pour l'afficher. Je m'inscris!