4.1 Fermeture du fichier et gestion des erreurs
Parfois, lors de la lecture d'un fichier, des erreurs ou des exceptions se produisent et le fichier reste non fermé. Cela peut potentiellement entraîner une fuite de mémoire ou une fuite de file handler. C'est pourquoi il faut envelopper le travail avec un fichier dans un bloc try-except.
Supposons que vous aviez le code :
file = open('example.txt', 'a') # Ouvrir le fichier
file.write("This is a new line added to the file.")
file.close() # Fermer le fichier
Il faut l'envelopper dans un bloc try-except :
try:
file = open('example.txt', 'a') # Ouvrir le fichier
file.write("This is a new line added to the file.")
file.close() # Fermer le fichier
except FileNotFoundError:
print("File not found")
file.close() # Fermer le fichier
Pour éviter d'écrire deux fois la méthode close(), on peut la déplacer dans le bloc finally :
try:
file = open('example.txt', 'a') # Ouvrir le fichier
file.write("This is a new line added to the file.")
except FileNotFoundError:
print("File not found")
finally:
file.close() # Fermer le fichier
Ce code est élégant, mais… ne fonctionne pas, car la variable file est définie uniquement dans le bloc try et n'est pas accessible dans les blocs except et finally.
Donc, nous devons définir la variable un niveau au-dessus :
file = None
try:
file = open('example.txt', 'a') # Ouvrir le fichier
file.write("This is a new line added to the file.")
except FileNotFoundError:
print("File not found")
finally:
file.close() # Fermer le fichier
Cette solution est meilleure, mais elle a aussi des inconvénients. Par exemple, si le fichier n'est jamais ouvert, la variable file contiendra None. Et alors tenter de fermer le fichier déclenchera une erreur - ce sera une tentative d'appeler la méthode close() sur un objet inexistant.
Donc, nous devons ajouter une vérification avant d'appeler la méthode close() :
file = None
try:
file = open('example.txt', 'a') # Ouvrir le fichier
file.write("This is a new line added to the file.")
except FileNotFoundError:
print("File not found")
finally:
if file:
file.close() # Fermer le fichier
Si tu es surpris que 3 lignes de code se soient transformées en 9, tu n'es pas seul. Heureusement, il existe déjà une solution prête pour ce problème, dont nous parlerons ensuite.
4.2 L'opérateur with
L'opérateur with en Python offre un moyen pratique de gérer les ressources, comme les fichiers, en assurant leur fermeture automatique après l'achèvement du bloc with. Cela simplifie le code et prévient les fuites de ressources, comme les fichiers non fermés.
Syntaxe générale de l'opérateur with :
with expression as variable:
travail avec la variable
L'opérateur with est utilisé pour envelopper l'exécution d'un bloc de code avec un gestionnaire de contexte. Lors de l'utilisation de l'opérateur with, Python appelle automatiquement les méthodes __enter__() et __exit__() de l'objet gestionnaire de contexte, ce qui simplifie la gestion des ressources.
Exemple d'utilisation de with pour travailler avec les fichiers :
with open('example.txt', 'w') as file:
file.write("Hello, World!\n")
file.write("This is a test file.\n")
Dans cet exemple, le fichier example.txt est ouvert en mode écriture, et le nom du fichier est lié à la variable file. Le bloc de code à l'intérieur de with ferme automatiquement le fichier après avoir effectué toutes les opérations d'écriture.
4.3 Fermeture automatique du fichier
L'un des principaux avantages de l'utilisation de l'opérateur with est la fermeture automatique du fichier après la fin du bloc de code. Cela se produit même en cas d'exception, ce qui rend le code plus sûr et fiable.
Exemple de fermeture automatique du fichier :
try:
with open('example.txt', 'w') as file:
file.write("Hello, World!\n")
file.write("This is a test file.\n")
# Exception pour vérifier que le fichier se ferme malgré tout
raise Exception("Something went wrong")
except Exception as e:
print(f"Caught an exception: {e}")
# À ce stade, le fichier est déjà fermé
Utilise toujours l'opérateur with lorsque tu travailles avec des fichiers. C'est simple et ça permet d'éviter de nombreuses erreurs.
4.4 Sous le capot de l'opérateur with
Au cœur de l'opérateur with se trouvent les méthodes __enter__() et __exit__(), qui doivent être implémentées dans la classe, utilisée comme gestionnaire de contexte.
Pour qu'un objet puisse être utilisé avec l'opérateur with, il doit implémenter les méthodes __enter__() et __exit__(). Ces méthodes définissent le comportement lors de l'entrée et de la sortie du contexte.
La méthode __enter__()
La méthode __enter__() est appelée à l'entrée du bloc with. Elle initialise la ressource et renvoie l'objet qui sera lié à la variable spécifiée après as.
La méthode __exit__()
La méthode __exit__() est appelée à la sortie du bloc with. Elle effectue des actions de nettoyage, comme la libération de ressources ou la fermeture de fichiers. La méthode prend trois arguments : exc_type, exc_val et exc_tb, qui contiennent des informations sur l'exception si elle s'est produite.
-
exc_type: type de l'exception (par exemple,ZeroDivisionError). -
exc_val: valeur de l'exception (par exemple, message d'erreur). exc_tb: traçage de l'exception stack.
Si la méthode __exit__() renvoie True, alors l'exception sera supprimée. Si elle renvoie False, l'exception sera relancée.
Exemple :
class MyContextManager:
def __enter__(self):
print("Entering the context")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type:
print(f"An exception occurred: {exc_type}, {exc_val}")
return False # L'exception n'est pas supprimée
with MyContextManager() as manager:
print("Inside the with block")
GO TO FULL VERSION