Sous-sections


7. Entrées et Sorties

Il y a plusieurs manières de présenter l'affichage produit par un programme; les données peuvent être imprimées sous une forme humainement lisible, ou être écrites dans un fichier pour un usage ultérieur. Ce chapitre présentera certaines de ces possibilités.

7.1 Un Formatage de Sortie Plus Fantaisiste

Jusqu'ici nous avons rencontré deux manières d'afficher des valeurs: les instructions d'expression et l'instruction print. (Une troisième manière est d'utiliser la méthode write() des objets fichier; le fichier de sortie standard peut être référencé par sys.stdout. Voyez le manuel Library Reference pour plus d'informations.)

Vous souhaiterez souvent avoir plus de contrôle sur le formatage de vos sorties que d'imprimer simplement des valeurs séparées par des espaces. Il y a deux manières de formater vos sorties; la première manière est de faire toutes les manipulations de chaînes de caractères vous-même; en utilisant les opérations de concaténation et de découpage de chaînes de caractères, vous pouvez créer n'importe quel format que vous puissiez imaginer. Le module standard string contient quelques opérations utiles pour remplir des chaînes de caractères à une largeur de colonne donnée; celles-ci seront discutées sous peu. La deuxième manière est d'utiliser l'opérateur % avec une chaîne de caractères comme argument de gauche, % interprète l'argument de gauche comme une chaîne de formatage comme pour la fonction sprintf() du langage C à appliquer à l'argument de droite, et retourne une chaîne de caractères résultant de cette opération de formatage.

Il reste naturellement une question: comment convertissez-vous des valeurs en chaînes de caractères? Heureusement, Python a un moyen de convertir n'importe quelle valeur en chaîne de caractères: passez-la à la fonction repr(), ou écrivez juste la valeur entre des guillemets renversés (anti-quotes: ``). Quelques exemples:

>>> x = 10 * 3.14
>>> y = 200*200
>>> s = 'La valeur de x est ' + `x` + ', et y est ' + `y` + '...'
>>> print s
La valeur de x est 31.4, et y est 40000...
>>> # Les anti-quotes marchent avec d'autres types en dehors des nombres:
... p = [x, y]
>>> ps = repr(p)
>>> ps
'[31.4, 40000]'
>>> # Convertir une chaîne ajoute des quotes de chaîne et des antislash:
... salut = 'salut, monde\n'
>>> saluts = `salut`
>>> print saluts
'salut, monde\012'
>>> # L'argument des anti-quotes peut être un tuple:
... `x, y, ('spam', 'eggs')`
"(31.4, 40000, ('spam', 'eggs'))"

Voici deux manières d'écrire une table des carrés et des cubes:

>>> import string
>>> for x in range(1, 11):
...     print string.rjust(`x`, 2), string.rjust(`x*x`, 3),
...     # Notez la virgule à la fin de la ligne précédente
...     print string.rjust(`x*x*x`, 4)
...
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000
>>> for x in range(1,11):
...     print '%2d %3d %4d' % (x, x*x, x*x*x)
... 
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000

(Notez qu'un espace entre chaque colonne a été ajouté à cause de la façon dont print fonctionne: elle ajoute toujours des espaces entre ses arguments.)

Cet exemple présente la fonction string.rjust(), qui justifie à droite une chaîne de caractères dans un champ d'une largeur donnée en la complétant avec des espaces du côté gauche. Il y a les fonctions semblables string.ljust() et string.center(). Ces fonctions n'écrivent rien, elles renvoient juste une nouvelle chaîne de caractères. Si la chaîne de caractères d'entrée est trop longue, elles ne la tronquent pas, mais la renvoient sans changement; ceci gâchera votre présentation de colonne mais c'est habituellement mieux que l'alternative, qui serait de tricher au sujet d'une valeur. (Si vous voulez vraiment la troncature vous pouvez toujours ajouter une opération de découpage, comme "string.ljust(x, n)[0:n]".)

Il y a une autre fonction, string.zfill(), qui complète une chaîne de caractères numérique du côté gauche avec des zéros. Elle sait gérer les signes positifs et négatifs :

>>> import string
>>> string.zfill('12', 5)
'00012'
>>> string.zfill('-3.14', 7)
'-003.14'
>>> string.zfill('3.14159265359', 5)
'3.14159265359'

L'utilisation de l'opérateur % ressemble à ceci:

>>> import math
>>> print 'La valeur de PI est approximativement %5.3f.' % math.pi
La valeur de PI est approximativement 3.142.

S'il y a plus d'un descripteur de format dans la chaîne de caractères, vous passez un tuple comme opérande de droite, par exemple.

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> for nom, telephone in table.items():
...     print '%-10s ==> %10d' % (nom, telephone)
... 
Jack       ==>       4098
Dcab       ==>    8637678
Sjoerd     ==>       4127

La plupart des formats fonctionnent exactement comme en C et exigent que vous passiez le type approprié; cependant, si vous ne le faites pas vous obtenez une exception, pas un core dump. Le format de %s est moins strict : si l'argument correspondant n'est pas un objet chaîne de caractères, il est converti en chaîne de caractères en utilisant la fonction intégrée str(). Utiliser * pour passer la largeur ou la précision comme argument (entier) séparé est possible. Les formats %n et %p du C ne sont pas supportés.

Si vous avez une chaîne de caractères de formatage vraiment longue que vous ne voulez pas fractionner, il serait élégant de pouvoir référencer les variables à formater par leur nom et pas par leur position. Ceci peut être fait en utilisant une extension des formats du C en utilisant la forme %(name)format, par exemple.

>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print 'Jack: %(Jack)d; Sjoerd: %(Sjoerd)d; Dcab: %(Dcab)d' % table
Jack: 4098; Sjoerd: 4127; Dcab: 8637678

C'est particulièrement utile en combinaison avec la fonction intégrée vars(), qui renvoie un dictionnaire contenant toutes les variables locales.


7.2 Lire et Ecrire des Fichiers

open() renvoie un objet de type fichier, et est utilisée plus généralement avec deux arguments: "open(nomfichier, mode)".

>>> f=open('/tmp/fichiertravail', 'w')
>>> print f
<open file '/tmp/fichiertravail', mode 'w' at 80a0960>

Le premier argument est une chaîne de caractères contenant le nom du fichier. Le deuxième argument est une autre chaîne de caractères contenant quelques caractères décrivant la manière d'utiliser le fichier. mode vaut 'r' quand le fichier doit être seulement lu, 'w' pour seulement écrit (un fichier déjà existant avec le même nom sera effacé), et 'a' ouvre le fichier en ajout; les données écrites dans le fichier seront automatiquement ajoutées à la fin. 'r+' ouvre le fichier pour la lecture et l'écriture. L'argument mode est facultatif; 'r' sera pris par défaut s'il est omis.

Sur Windows et Macintosh, 'b' ajouté au mode ouvre fichier en mode binaire, donc il y a aussi des modes comme 'rb', 'wb', et 'r+b'. Windows fait la distinction entre fichier texte et binaire ; les caractères de fin de ligne dans des fichiers texte sont automatiquement modifiés légèrement quand des données sont lues ou écrites. Cette modification imperceptible des données du fichier marche très bien pour des fichiers textes ASCII, mais elle altèrera des données binaires comme dans des fichiers JPEG ou .EXE. Faites très attention à utiliser le mode binaire en lisant et en écrivant de tels fichiers. (notez que la sémantique précise du mode texte sur le Macintosh dépend de la bibliothèque C utilisée.)


7.2.1 Méthodes des Objets Fichier

Le reste des exemples dans cette section supposera qu'un objet fichier appelé f a déjà été créé.

Pour lire le contenu d'un fichier, appeler f.read(taille), qui lit une certaine quantité de données et les retourne en tant que chaîne de caractères. taille est un argument numérique facultatif. Quand taille est omis ou négatif, le contenu entier du fichier sera lu et retourné; c'est votre problème si le fichier est deux fois plus grand que la mémoire de votre machine. Autrement, au plus taille octets sont lus et retournés. Si la fin du fichier a été atteinte, f.read() renverra une chaîne de caractères vide ("").

>>> f.read()
'Ceci est le fichier entier.\012'
>>> f.read()
''

f.readline() lit une seule ligne à partir du fichier; un caractère de fin de ligne (\n) est laissé à l'extrémité de la chaîne de caractères lue, et est seulement omis sur la dernière ligne du fichier si le fichier ne se termine pas par une fin de ligne. Ceci rend la valeur de retour non ambiguë; si f.readline() renvoie une chaîne de caractères vide, la fin du fichier a été atteinte, alors qu'une fin de ligne est représentée par '\n', une chaîne de caractères contenant seulement une seule fin de ligne.

>>> f.readline()
'Ceci est la première ligne du fichier.\012'
>>> f.readline()
'Deuxième ligne du fichier\012'
>>> f.readline()
''

f.readlines() utilise f.readline() de façon répétitive, et retourne une liste contenant toutes les lignes de données du fichier.

>>> f.readlines()
['Ceci est la première ligne du fichier.\012', 'Deuxième ligne du fichier\012']

f.write(chaine) écrit le contenu de chaine dans le fichier, en retournant None.

>>> f.write('Voici un test\n')

f.tell() renvoie un nombre entier donnant la position actuelle dans le fichier associé à l'objet fichier, mesurée en octets depuis le début du fichier. Pour changer la position dans l'objet fichier, employez "f.seek(decalage, point_depart)". La position est calculée en ajoutant decalage à un point de référence; le point de référence est choisi par l'argument point_depart. Une valeur de 0 pour point_depart fait démarrer au début du fichier, 1 utilise la position courante du fichier, et 2 utilise la fin de fichier comme point de référence. point_depart peut être omis et prend alors 0 pour valeur par défaut comme point de référence.

>>> f=open('/tmp/fichiertravail', 'r+')
>>> f.write('0123456789abcdef')
>>> f.seek(5)     # Saute jusqu'au 5ème octet dans le fichier
>>> f.read(1)        
'5'
>>> f.seek(-3, 2) # Saute jusqu'au 3ème octet avant la fin
>>> f.read(1)
'd'

Quand vous en avez terminé avec un fichier, appeler f.close() pour le fermer et libérer toutes les ressources système utilisées par le fichier ouvert. Après avoir appelé f.close(), les tentatives d'utiliser l'objet fichier échoueront automatiquement.

>>> f.close()
>>> f.read()
Traceback (innermost last):
  File "<stdin>", line 1, in ?
ValueError: I/O operation on closed file

Les objets fichier ont quelques méthodes supplémentaires, telles que isatty() et truncate() qui sont moins fréquemment utilisées; consultez la Library Reference pour un guide complet des objets fichier.


7.2.2 Le Module pickle

Les chaînes de caractères peuvent facilement être écrites et lues dans un fichier. Les nombres demandent un peu plus d'effort, puisque la méthode read() renvoie seulement les chaînes de caractères, qui devront être passées vers une fonction comme string.atoi(), qui prend une chaîne de caractères comme '123' et renvoie sa valeur numérique 123. Cependant, quand vous voulez sauvegarder des types de données plus complexes comme des listes, des dictionnaires, ou des instances de classe, les choses deviennent beaucoup plus compliquées.

Plutôt que faire écrire et déboguer constamment par les utilisateurs le code pour sauvegarder des types de données complexes, Python fournit un module standard appelé pickle. C'est un module étonnant qui peut prendre presque n'importe quel objet Python (même quelques formes de code Python!), et le convertir en une représentation sous forme de chaîne de caractères; ce processus s'appelle pickling. Reconstruire l'objet à partir de sa représentation en chaîne de caractères s'appelle unpickling. Entre pickling et unpickling, la chaîne de caractères représentant l'objet a pu avoir été enregistrée dans un fichier ou des données, ou avoir été envoyée à une machine éloignée via une connexion réseau.

Si vous avez un objet x, et un objet fichier f ouvert en écriture, la voie la plus simple de ``pickler'' l'objet prend seulement une ligne de code:

pickle.dump(x, f)

Pour ``unpickler'' l'objet, si f est un objet fichier ouvert en lecture:

x = pickle.load(f)

(il y a d'autres variantes pour ceci, utilisées pour ``pickler'' beaucoup d'objets ou quand vous ne voulez pas écrire les données ``picklées'' dans un fichier; consultez la documentation complète pour pickle dans la Library Reference.)

pickle est le moyen standard pour enregistrer des objets Python et les réutiliser dans d'autres programmes ou dans une future invocation du même programme; le terme technique pour ceci est la persistance d'un objet. Puisque pickle est très largement répandu, beaucoup d'auteurs qui écrivent des extensions pour Python prennent soin de s'assurer que de nouveaux types de données tels que des matrices peuvent être correctement ``picklés'' et ``unpicklés''.


See About this document... for information on suggesting changes.