Canaux de communication

In [ ]:
import sys

Canaux de communication

Un programme n'a d'utilité que s'il échange de l'information avec l'extérieur. Pour cela il doit ouvrir un canal de communication vers une source ou une destination. Une fois ce canal ouvert, il peut émettre ou recevoir des caractères sur ce canal. Le programme ferme le canal en fin de communication.

Création d'un fichier de texte

La création d'un fichier est un exemple où le programme doit émettre de l'information vers une destination.

Supposons que nous voulions créer un fichier de texte quantique.txt contenant les 5 lignes ci-dessous :

Max Planck
Erwin Schrödinger
Albert Einstein
Werner Heiseinberg
Louis de Broglie

La première étape est de créer un canal de communication du programme vers le fichier quantique.txt :

In [ ]:
fd = open("quantique.txt", "w")

L'argument "w" indique que le canal doit être ouvert en écriture (write). La fonction open crée le canal et retourne une valeur qui est mémorisée dans la variable flux.

In [ ]:
fd
Out[ ]:
<_io.TextIOWrapper name='quantique.txt' mode='w' encoding='UTF-8'>

La valeur retournée par open possède un type bien particulier que Python appelle _io.TextIOWrapper. Nous appelerons ce type plus simplement le type flux.

L'affichage de la valeur fd ci-dessus indique :

  • qu'il s'agit d'un canal de sortie (mode='w')
  • que la destination est le fichier 'quantique.txt' ( name='quantique.txt')
  • que les données émises sont des caractères Unicode encodés en utf-8 (encoding='UTF-8')

La fonction write permet d'envoyer des caractères sur le flux fd :

In [ ]:
fd.write("Max Planck")
fd.write("\n")
fd.write("Erwin Schrödinger\n")
fd.write("Albert Einstein\nWerner Heiseinberg\n")
fd.write("Louis de Broglie\n")
Out[ ]:
17

Lorsque tous les caractères ont été transmis le flux doit être fermé :

In [ ]:
fd.close()

Observons si le fichier a bien été créé :

In [ ]:
!ls -l quantique.txt
-rw-rw-r-- 1 denis denis 82 nov.  27 14:44 quantique.txt

Un fichier quantique.txt a bien été créé. Ce fichier contient 82 octets. Le programme cat permet de visualiser le contenu textuel du fichier :

In [ ]:
!cat quantique.txt
Max Planck
Erwin Schrödinger
Albert Einstein
Werner Heiseinberg
Louis de Broglie

Le programme xxd permet de visualiser le contenu binaire du fichier :

In [ ]:
!xxd quantique.txt
00000000: 4d61 7820 506c 616e 636b 0a45 7277 696e  Max Planck.Erwin
00000010: 2053 6368 72c3 b664 696e 6765 720a 416c   Schr..dinger.Al
00000020: 6265 7274 2045 696e 7374 6569 6e0a 5765  bert Einstein.We
00000030: 726e 6572 2048 6569 7365 696e 6265 7267  rner Heiseinberg
00000040: 0a4c 6f75 6973 2064 6520 4272 6f67 6c69  .Louis de Brogli
00000050: 650a                                     e.

Remarquez que le caractère 'ö' est encodé en utf-8 par les deux octets C3B6.

La fonction print peut être utilisée à la place de la fonction write. La syntaxe est un peu différente :

In [ ]:
fd = open("quantique2.txt", "w")
print("Max Plank", file=fd)
print("Erwin Schrödinger", file=fd)
print("Albert Einstein", file=fd)
print("Werner Heiseinberg", file=fd)
print("Louis de Broglie", file=fd)
fd.close()

Remarquez que contrairement à write, la fonction print ajoute un caractère saut de ligne après l'envoi de la chaîne de caractères passée en argument.

In [ ]:
!cat quantique2.txt
Max Plank
Erwin Schrödinger
Albert Einstein
Werner Heiseinberg
Louis de Broglie

Remarque importante : La création d'un flux en écriture vers un fichier qui existe déjà supprime le contenu de ce fichier. Il est possible d'ouvrir un flux dans le mode append. Dans ce cas le contenu du fichier est préservé et les caractères envoyés sont ajoutés à la fin du fichier :

In [ ]:
fd = open("quantique.txt", "a")
print("Niels Bohr",file=fd)
fd.close()
In [ ]:
!cat quantique.txt
Max Planck
Erwin Schrödinger
Albert Einstein
Werner Heiseinberg
Louis de Broglie
Niels Bohr

Tout programme est connecté par défaut à un canal de sortie appelé sys.stdout (sortie standard). Nul besoin d'utiliser la fonction open pour cela. Lorsqu'un programme envoie des caractères sur ce canal l'effet produit dépend du contexte dans lequel ce programme est exécuté. Dans le contexte d'un notebook Jupyter, les caractères sont écrits en dessous de la cellule de code Python :

In [ ]:
print("Bonjour\nà\ntous", file=sys.stdout)
Bonjour
à
tous

Lorsque le flux n'est pas précisé, les caractères sont envoyés par défaut sur la sortie standard :

In [ ]:
print("Bonjour\nà\ntous")
Bonjour
à
tous

Lecture d'un fichier de texte

Pour lire un fichier de texte il faut créer un canal de communication du fichier vers le programme. On utilise pour cela le mode "r" (read) de la fonction open :

In [ ]:
fd = open("quantique.txt", "r")
In [ ]:
fd
Out[ ]:
<_io.TextIOWrapper name='quantique.txt' mode='r' encoding='UTF-8'>

La fonction read lit le flux de caractères jusqu'à obtenir le caractère EOF (End Of File). La fonction read retourne les caractères lus sous la forme d'un str.

In [ ]:
fd.read()
Out[ ]:
'Max Planck\nErwin Schrödinger\nAlbert Einstein\nWerner Heiseinberg\nLouis de Broglie\nNiels Bohr\n'

Un nouvel appel à read retourne la chaîne vide puisque tous les caractères du fichier ont déjà été lus :

In [ ]:
fd.read()
Out[ ]:
''

Lorsque le fichier a été lu on referme le flux.

In [ ]:
fd.close()

Les fichiers peuvent contenir de grandes quantités d'information. La mémoire RAM est une ressource limitée et précieuse qu'il faut utiliser et partager avec parcimonie. Il se peut d'ailleurs que la taille du fichier dépasse la capacité de la RAM. Une bonne pratique est donc de lire et de traiter le fichier ligne par ligne :

In [ ]:
fd = open("quantique.txt", "r")
fd.readline()
Out[ ]:
'Max Planck\n'
In [ ]:
fd.readline()
Out[ ]:
'Erwin Schrödinger\n'

La fonction readline lit le flux de caractères jusqu'à obtenir le caractère '\n' (saut de ligne) ou le caractère EOF. La fonction retourne les caractères lus, y compris l'éventuel caractère '\n'. Chaque appel à readline retourne donc une nouvelle ligne du fichier. Une chaîne vide comme valeur de retour signifie que le fichier a été entièrement lu.

In [ ]:
fd = open("quantique.txt", "r")
ligne = fd.readline()       # Lecture de la première ligne
while ligne != '':          # Tant que EOF n'est pas atteint
    nom = ligne.upper()     #     Traitement
    print(nom)              #     de la ligne
    ligne = fd.readline()   #     Lecture de la ligne suivante
fd.close()
MAX PLANCK

ERWIN SCHRÖDINGER

ALBERT EINSTEIN

WERNER HEISEINBERG

LOUIS DE BROGLIE

NIELS BOHR

Remarquez ici que les noms des physiciens sont séparés par deux caractères '\n'. Le premier est celui retourné par la fonction readline. Le second est celui ajouté par la fonction print.