Gestionnaire de contexte
Pour lire ou écrire un fichier, il faut commencer par l'ouvrir et terminer en le fermant, toutes les opérations sur le fichier se passant entre ces deux opérations. C'est ce que l'on appelle un contexte dans lequel on rentre pour pouvoir effectuer une série d'opérations avant de le quitter. Python propose une construction permettant de rendre le code plus lisible dans de telles situations, et c'est le sujet de cette section.
Fermeture du fichier
Comme on l'a déjà dit plusieurs fois, il est important de fermer un fichier ouvert une fois que les opérations sur ce dernier sont finies. Le problème qui peut survenir avec tous les exemples que l'on a vu précédemment est que, si une exception se produit pendant la lecture ou l'écriture du fichier, l'exécution saute dans le bloc except
correspondant et la fermeture n'aura jamais lieu.
Pour résoudre ce problème, on pourrait se dire qu'il suffit de placer la fermeture du fichier dans un bloc finally
pour être sûr qu'elle soit exécutée à tous les coups :
Cette solution n'est pas encore idéale car une erreur sera produite par le close
dans le cas où le fichier n'a pas su être ouvert. En effet, dans ce cas, la variable file
n'existe pas et on se retrouve avec l'erreur suivante :
Fichier introuvable. Traceback (most recent call last): File "program.py", line 9, in <module> print(file) NameError: name 'file' is not defined
On va donc rajouter un nouveau bloc try
qui va exclure l'ouverture du fichier, pour pouvoir lui attacher un bloc finally
qui ferme le fichier. On sera ainsi certain que si le fichier a été ouvert, il sera d'office fermé. Le programme devient donc :
Ce code devient difficilement lisible, mais propose une solution élégante pour s'assurer de la fermeture du fichier, et donc de la libération des ressources, dans tous les cas.
Instruction with
Python propose l'instruction with
pour proprement gérer un contexte et automatiquement libérer les ressources au moment où le contexte est quitté. Voyons d'abord comment l'exemple précédent se réécrit :
On utilise donc le mot réservé with
suivi de l'appel de fonction qui crée l'objet qui sera utilisé dans le contexte, à savoir le fichier. On peut affecter le résultat renvoyé par la fonction à une variable en plaçant le nom désiré après le mot réservé as
. Le bloc de code qui suit sera exécuté dans le contexte et la variable initialisée par le with
y sera accessible. Une fois la fin de ce bloc atteint, la ressource du contexte sera libérée, c'est-à-dire que le fichier sera fermé.
On peut ouvrir plusieurs contextes avec la même instruction with
. Il suffit pour cela de simplement les séparer par des virgules, chacun ayant sa propre variable associée, évidemment. Voici, par exemple, comment on pourrait très facilement copier le contenu du fichier texte a.txt
vers le fichier b.txt
:
Une fois le bloc with
terminé, les deux fichiers ouverts sont automatiquement fermés. Pour être complet, il faudrait évidemment ajouter la gestion des erreurs d'entrée/sortie sur cet exemple. De plus, ce serait mieux de vérifier que le fichier destination n'existe pas déjà si on veut éviter que ce dernier ne soit écrasé, en utilisant le mode x
, par exemple.