with
Les déclarations ou les gestionnaires de contexte sont là pour aider les ressources (bien qu'ils puissent être utilisés pour bien d'autres choses).
Disons que vous avez ouvert un fichier en écriture :
f = open(path, "w")
Vous avez maintenant un handle de fichier ouvert. Pendant la manipulation de votre fichier, aucun autre programme ne peut y écrire. Pour permettre à d'autres programmes d'y écrire, vous devez fermer l'identificateur de fichier :
f.close()
Mais, avant de fermer votre fichier, une erreur s'est produite :
f = open(path, "w")
data = 3/0 # Tried dividing by zero. Raised ZeroDivisionError
f.write(data)
f.close()
Ce qui va se passer maintenant, c'est que la fonction ou le programme entier va se terminer, tout en laissant votre fichier avec un handle ouvert. (CPython nettoie les handles à la fin du programme et les handles sont libérés en même temps que le programme, mais il ne faut pas compter là-dessus).
Une instruction with garantit que dès que vous quittez l'indentation, elle fermera le gestionnaire de fichier :
with open(path, "w") as f:
data = 3/0 # Tried dividing by zero. Raised ZeroDivisionError
f.write(data)
# In here the file is already closed automatically, no matter what happened.
with
Les déclarations peuvent être utilisées pour bien d'autres choses encore. Par exemple : threading.Lock()
lock = threading.Lock()
with lock: # Lock is acquired
do stuff...
# Lock is automatically released.
Presque tout ce qui est fait avec un gestionnaire de contexte peut être fait avec try: ... finally: ...
mais les gestionnaires de contexte sont plus agréables à utiliser, plus confortables, plus lisibles et, grâce à l'implémentation des __enter__
y __exit__
fournir une interface facile à utiliser.
La création de gestionnaires de contexte se fait en mettant en œuvre __enter__()
y __exit__()
dans une classe normale.
__enter__()
indique ce qu'il faut faire lorsqu'un gestionnaire de contexte démarre et __exit__()
lorsqu'un gestionnaire de contexte existe (en donnant l'exception au __exit__()
si une exception s'est produite)
Un raccourci pour créer des gestionnaires de contexte peut être trouvé dans contextlib . Il enveloppe un générateur comme gestionnaire de contexte.