Mis à jour le vendredi 17 novembre 2017
  • 40 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

Ce cours existe en livre papier.

Vous pouvez obtenir un certificat de réussite à l'issue de ce cours.

Vous pouvez être accompagné et mentoré par un professeur particulier par visioconférence sur ce cours.

J'ai tout compris !

Les fichiers

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Poursuivons notre tour d'horizon des principaux objets. Nous allons voir dans ce chapitre les fichiers, comment les ouvrir, les lire, écrire dedans.

Nous finirons ce chapitre en voyant comment sauvegarder nos objets dans des fichiers, afin de les utiliser d'une session à l'autre de notre programme.

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.

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, hormis 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 la somme que nous avions en poche au moment de quitter le casino, 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'estC:\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 moduleos, qui s'appellechdir(Change Directory).

>>> import os
>>> os.chdir("C:/tests python")
>>>

Pour que cette instruction fonctionne, le répertoire doit exister. Modifiez la chaîne passée en paramètre deos.chdiren fonction du dossier dans lequel vous souhaitez vous déplacer.

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 fonctionne très bien même sous Windows.

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 vraisemblablement depuis /.

Par exemple, sous Windows, si on a un fichier nomméfic.txt, contenu dans un dossiertest, lui-même présent sur le disqueC:, le chemin absolu menant à notre fichier seraC:\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 dossierC:\testet que l'on souhaite accéder au fichierfic.txtcontenu dans ce même dossier, le chemin relatif menant à ce fichier sera tout simplementfic.txt.

Maintenant, si on se trouve dansC:, notre chemin relatif seratest\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 dossiertestque tout se passe. Nous avons deux sous-répertoires nommésrep1etrep2. Dansrep1, nous avons un seul fichier :fic1.txt. Dansrep2, nous avons deux fichiers :fic2.txtetfic3.txt.

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

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 l'intégralité du chemin menant au fichier, peu importe l'endroit où on se trouve. Un chemin absolu permet d'accéder à un endroit dans le disque quel que soit le répertoire de travail courant. L'inconvénient de cette méthode, c'est qu'on doit préalablement savoir où se trouvent, sur le disque, les fichiers dont on a besoin.

Le chemin relatif décrit la succession de répertoires à parcourir en prenant comme point d'origine non pas la racine, ou le périphérique sur lequel est stockée la cible, mais le répertoire dans lequel on se trouve. Cela présente certains avantages quand on code un projet, on n'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 toutes circonstances.

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 fonctionos.getcwd()(CWD = « Current Working Directory »).

Cela devrait donc vous suffire. Pour les démonstrations qui vont suivre, placez-vous, à l'aide deos.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'appelerfichier.txtet 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 fonctionopen, disponible sans avoir besoin de rien importer. Elle prend en paramètre :

  • 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 :

  • '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 signebpour ouvrir le fichier en mode binaire. Nous en verrons plus loin l'utilité, c'est un mode un peu particulier.

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

>>> 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 suivant 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 fonctionopencrée donc un fichier. Elle renvoie un objet de la classeTextIoWrapper. Par la suite, nous allons utiliser des méthodes de cette classe pour interagir avec le fichier.

Le type de l'objet doit vous surprendre quelque peu. Cela aurait très bien pu être un typefileaprès tout. En fait,openpermet d'ouvrir un fichier, maisTextIoWrapperest utilisé dans d'autres circonstances, pour afficher du texte à l'écran par exemple. Bon, cela ne nous concerne pas trop ici, je ne vais pas m'y attarder.

Fermer le fichier

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

>>> mon_fichier.close()
>>>

Lire l'intégralité du fichier

Pour ce faire, on utilise la méthodereadde la classeTextIoWrapper. Elle renvoie l'intégralité du fichier :

>>> 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éthodereadrenvoie tout le contenu du 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 variablecontenules signes\ntraduisant 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,splitla chaîne pour parcourir chaque ligne et les traiter… bref, tout est possible.

Écriture dans un fichier

Bien entendu, il nous faut ouvrir le fichier avant tout. Vous pouvez utiliser le modewou le modea. 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. 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éthodewriteen lui passant en paramètre la chaîne à écrire dans le fichier. Elle renvoie 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.

>>> 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éthodewriten'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 lus.

Le moduleoscontient 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é.

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 pas garde, le fichier restera ouvert.

Comme je vous l'ai dit, c'est plutôt gênant et cela 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 :

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 trouverwithdans la manipulation d'autres objets mais nous ne le verrons pas ici.

  • Notre objet. Ici, on appelleopenqui va renvoyer un objetTextIOWrapper(notre fichier).

  • Le mot-cléasque 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 ?

>>> with open('fichier.txt', 'r') as mon_fichier:
...     texte = mon_fichier.read()
... 
>>>

Cela signifie simplement que, si une exception se produit, le fichier sera tout de même fermé à la fin du bloc.

Le mot-cléwithpermet de créer un "context manager" (gestionnaire de contexte) qui vérifie que le fichier est ouvert et fermé, même si des erreurs se produisent pendant le bloc. Vous verrez plus loin d'autres objets utilisant le même mécanisme.

Vous pouvez appelermon_fichier.closedpour vérifier que le fichier est refermé. Si le fichier est fermé,mon_fichier.closedvaudraTrue.

Il est inutile, par conséquent, de fermer le fichier à la fin du blocwith. 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 modulepickle, dans lequel nous allons apprendre à sauvegarder nos objets dans des fichiers.

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 modulepickleque 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 (à condition, naturellement, que celui-ci prenne en charge Python).

Enregistrer un objet dans un fichier

Il nous faut naturellement d'abord importer le modulepickle.

>>> import pickle
>>>

On va ensuite utiliser deux classes incluses dans ce module : la classePickleret la classeUnpickler.

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

Pour créer notre objetPickler, nous allons l'appeler en passant en paramètre le fichier dans lequel nous allons enregistrer notre objet.

>>> with open('donnees', 'wb') as fichier:
...     mon_pickler = pickle.Pickler(fichier)
...     # enregistrement ...
... 
>>>

Quand nous allons enregistrer nos objets, ce sera dans le fichierdonnees. 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 fichierdonneesen mode d'écriture binaire. Il suffit de rajouter, derrière la lettre symbolisant le mode, la lettrebpour indiquer un mode binaire.

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

Bon. Maintenant que notre pickler est créé, nous allons enregistrer un ou plusieurs objets dans notre fichier. Là, c'est à vous de voir comment vous voulez vous organiser, cela 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éthodedumpdu pickler pour enregistrer l'objet. Son emploi est des plus simples :

>>> 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 fichierdonneesqui contient… eh bien, notre dictionnaire contenant les scores de nos quatre joueurs. Si vous voulez enregistrer plusieurs objets, appelez de nouveau la méthodedumpavec 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 modulepickle. Cette fois, assez logiquement, c'est la classeUnpickler.

Commençons par créer notre objet. À sa création, on lui passe le fichier dans lequel on va lire les objets. Puisqu'on va lire, on change de mode, on repasse en moder, et mêmerbpuisque le fichier est binaire.

>>> 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éthodeloadde notre depickler. Elle renvoie le premier objet qui a été lu (s'il y en a plusieurs, il faut l'appeler plusieurs fois).

>>> 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 variablescore_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 devant être conservés alors que votre programme n'est pas lancé, c'est franchement très pratique.

En résumé

  • On peut ouvrir un fichier en utilisant la fonctionopenprenant en paramètre le chemin vers le fichier et le mode d'ouverture.

  • On peut lire dans un fichier en utilisant la méthoderead.

  • On peut écrire dans un fichier en utilisant la méthodewrite.

  • Un fichier doit être refermé après usage en utilisant la méthodeclose.

  • Le modulepickleest utilisé pour enregistrer des objets Python dans des fichiers et les recharger ensuite.

Exemple de certificat de réussite
Exemple de certificat de réussite