IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Python, de zéro


précédentsommairesuivant

XXII. L’accès aux fichiers

L’accès aux fichiers concerne toute façon de communiquer des informations entre un fichier disque et le programme. Cette communication peut être entrante, sortante ou bidirectionnelle.

XXII-1. L’accès au fichier

L’accès au fichier se fait par la fonction open(nomfichier, mode="r", buffering=-1; encoding=None). Le premier paramètre est le nom du fichier à ouvrir et le second sera le mode d’ouverture. On distingue 5 modes possibles :

  • mode "r" : accès en lecture seule. C’est le mode par défaut. Le fichier doit nécessairement exister ;
  • mode "w" : accès en écriture seule. Si le fichier n’existe pas, il est créé et s’il existe il est vidé ;
  • mode "x" : accès en écriture, mais exclusivement en création. Le fichier doit nécessairement ne pas exister ;
  • mode "a" : accès en écriture seule, mais en fin de fichier (mode « append »). Si le fichier n’existe pas, il est créé ;
  • mode "r+" : comme "r", mais autorise l’écriture ;
  • mode "w+" : comme "w", mais autorise la lecture ;
  • mode "x+" : comme "x", mais autorise la lecture ;
  • mode "a+" : comme "a", mais autorise la lecture ;

Ces modes peuvent en plus être agrémentés d’un "b" indiquant que la lecture ou l’écriture doivent se faire en mode binaire (ex "r+b"). Dans Python 2, ce mode n'a d'effet que sous Windows. En effet, Windows distingue ses fichiers textes par une suite de deux caractères ("\r\n") pour indiquer les fins de lignes. Et donc, toute écriture ou lecture en mode « non binaire » prendra en compte ces deux caractères ensemble comme représentant une fin de ligne ; alors que la lecture ou l’écriture en mode « binaire » ne les prendra pas en compte et les traitera l’un et l’autre de façon individuelle comme tout autre caractère.

Ce flag est aussi possible dans le monde Unix, mais n’aura d'effet que sous Python 3 permettant alors de différencier des fichiers textes (contenant des caractères encodés en utf-8) ou binaires (aucun encodage particulier).

Le troisième paramètre indique la façon de buffériser les entrées/sorties du fichier. Les valeurs possibles sont les suivantes :

  • -1 : laisse le système gérer. C’est la valeur par défaut ;
  • 0 : pas de bufférisation (toutes les IO sont synchrones) ;
  • 1 : bufférisation par ligne (n’a de sens que pour les fichiers textes) ;
  • Autre valeur positive : taille du buffer en octets (ne sera prise en compte que si elle est supérieure à 127 sinon elle est traitée comme 0).

Le quatrième paramètre (qui n'existe pas dans Python 2) permet de préciser l'encodage dans lequel est écrit le fichier. Mettre ce paramètre à None (qui est la valeur par défaut) permet de laisser la fonction le déterminer toute seule en analysant le fichier.

Dans Python 2, la fonction renvoie un objet file.

 
Sélectionnez
1.
2.
3.
>>> fp=open("/etc/passwd", "r")
>>> type (fp)
<type 'file'>

Dans Python 3, la fonction renvoie un objet _io.BufferedReader si le fichier a été ouvert en mode binaire en lecture, un objet _io.BufferedWriter si le fichier a été ouvert en mode binaire en écriture ou un objet _io.TextIOWrapper sinon.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
>>> rb=open("/etc/passwd", "rb")
>>> type (rb)
<class '_io.BufferedReader'>

>>> wb=open("/tmp/xxx", "wb")
>>> type (wb)
<class '_io.BufferedWriter'>

>>> r=open("/etc/passwd", "r")
>>> type (r)
<class '_io.TextIOWrapper'>

>>> w=open("/tmp/xxx", "w")
>>> type (w)
<class '_io.TextIOWrapper'>

Cette différence entre « binaire » et « texte » d’un côté et entre « lecture » et « écriture » de l’autre peut poser des soucis pour vérifier si un élément est ou n’est pas un fichier. Le module « io » contient un type IOBase commun permettant de simplifier ces vérifications.

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
>>> import io

>>> rb=open("/etc/passwd", "rb")
>>> isinstance(rb, io.IOBase)
True

>>> wb=open("/tmp/xxx", "wb")
>>> isinstance(wb, io.IOBase)
True

>>> r=open("/etc/passwd", "r")
>>> isinstance(r, io.IOBase)
True

>>> w=open("/tmp/xxx", "w")
>>> isinstance(w, io.IOBase)
True

Quoi qu’il en soit, c'est sur ces différents objets que se feront ensuite toutes les opérations de lecture et d’écriture (et pour simplifier, ils seront communément nommés file dans la suite du chapitre).

XXII-2. Traitements sur le fichier

Les traitements sur le fichier se font à travers l’objet renvoyé par open() . Chaque opération de lecture ou d’écriture déplace l'élément interne de l’objet (on le nomme généralement « tête de lecture/écriture ») d’autant de caractères, ce qui permet de répéter les opérations pour traiter tout le fichier.

Les opérations possibles sont les suivantes :

  • file.read(size=-1) : lecture de size octets. Si size vaut -1 (valeur par défaut), alors Python lit tout le fichier. La fonction renvoie une suite d’octets disponibles sous forme de str ou une chaîne vide s’il n’y a plus rien à lire ;

  • file.readline(size=-1) : lecture de size octets. Si size vaut -1 (valeur par défaut), alors Python lit autant qu’il le peut, mais s’arrête dès qu’il rencontre une fin de ligne ("\n" sous Unix, "\r\n" sous Windows). La fonction renvoie une suite d’octets disponibles sous forme de str correspondant donc à une ligne du fichier ou une chaîne vide quand tout a été lu. Dans le monde Windows, si le fichier a été ouvert en mode « non binaire » ("r" et non "rb") alors la lecture transforme le double caractère fin de ligne ("\r\n") en une fin de ligne standard ("\n"). Cette fonction n’a de sens que pour une lecture de fichiers textes ;

  • file.readlines(size=-1) : lecture de toutes les lignes jusqu’à concurrence de size octets. Si size vaut -1 (valeur par défaut), alors Python lit tout le fichier. La fonction renvoie une liste contenant toutes les lignes du fichier. Même remarque pour les fins de lignes éventuelles de ces chaînes. Cette fonction n’a de sens que pour une lecture de fichiers textes ;

  • file.write(str) : écriture de la chaîne str dans le fichier. Attention, la fonction ne rajoute pas de fin de ligne. Si l’utilisateur veut que cette fin de ligne soit écrite, il doit alors la positionner ("\n") dans la chaîne à écrire. Dans le monde Windows, si le fichier a été ouvert en mode « non binaire » ("w" et non "wb") alors l’écriture transforme ce caractère ("\n") en une fin de ligne adaptée ("\r\n") ;

  • file.writelines(iterable) : en considérant que l’itérable est un itérable de chaînes, la fonction écrit alors toutes ces chaînes dans le fichier. Même remarque pour les fins de lignes éventuelles de ces chaînes.

XXII-3. Autres fonctions de manipulation

L’objet file contient d’autres opérations spécifiques possibles :

  • file.tell() : renvoie la position en octets de la tête de lecture/écriture dans le fichier , position prise à partir du début du fichier ;

  • file.seek(pos, whence=0) : positionne la tête de lecture/écriture à la position demandée. La position dépend du paramètre whence. S’il est à 0, alors la position est calculée à partir du début du fichier. S’il est à 1, alors la position est calculée à partir de la position courante. S’il est à 2, alors la position (qui sera exprimée en négatif) est calculée par rapport à la fin du fichier. Dans tous les cas, la position finale de la tête ne pourra pas dépasser le début ou la fin de fichier. À noter que la position de la tête de lecture/écriture est aussi modifiée par toute écriture sur un fichier ouvert en mode « append » (elle se place automatiquement à la fin du fichier avant d’effectuer l’écriture) ;

  • file.truncate(size=-1) : coupe le fichier à la taille demandée. Si la taille vaut -1, alors coupe le fichier à la position actuelle de la tête de lecture/écriture. Si la taille demandée dépasse la taille initiale du fichier, alors le résultat dépend des plateformes (peut ne rien faire, peut rajouter des zéros ou peut rajouter des octets aléatoires). Le fichier doit avoir été ouvert en écriture (tous les modes sauf "r" ou "rb") ;

  • file.flush() : vide le tampon d’écriture. Les octets sont alors réellement écrits sur le fichier disque. À noter que si la fonction open() a été demandée avec le paramètre buffer à 0 (IO synchrones), le tampon est alors toujours vide, car les données sont réellement écrites sur le disque à chaque instruction d’écriture. Cette fonction n’a de sens que pour les fichiers ouverts en écriture ;

  • file.close() : ferme le fichier. Ça vide aussi son tampon d’écriture en finalisant les écritures restantes éventuelles.

XXII-4. Itération

En plus de pouvoir y effectuer les opérations détaillées précédemment, un objet file est aussi un itérable où chaque itération renvoie une ligne du fichier (ce qui n’a de sens bien évidemment que pour les fichiers textes).

C’est-à-dire qu’on peut traiter un fichier texte ligne par ligne au travers d’une simple boucle sur l’objet file.

Exemple :

 
Sélectionnez
1.
2.
3.
fp=open(fic, "r")
for lig in fp: print(lig)
fp.close()

Relativement équivalent à ceci :

 
Sélectionnez
1.
2.
3.
fp=open(fic, "r")
for lig in fp.readlines(): print(lig)
fp.close()

La même chose de façon plus classique :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
fp=open(fic, "r")
while True:
    lig=fp.readline()
    if not lig: break
    print(lig)
fp.close()

précédentsommairesuivant

Copyright © 2022 Svear (svear@free.fr) Permission est accordée de copier, distribuer ou modifier ce document selon les termes de la « Licence de Documentation Libre GNU » (GNU Free Documentation License), version 1.1 ou toute version ultérieure publiée par la Free Software Foundation.