Gestionnaire de Contexte Python

PythonBeginner
Pratiquer maintenant

Introduction

Bien que les gestionnaires de contexte (context managers) de Python soient largement utilisés, peu de gens comprennent réellement leur objectif. Ces instructions, couramment employées lors de la lecture et de l'écriture de fichiers, aident l'application à conserver la mémoire système et améliorent la gestion des ressources en garantissant que des ressources spécifiques ne sont utilisées que pour certains processus.

Dans ce laboratoire, vous apprendrez à utiliser l'instruction with pour la gestion automatique des ressources, puis vous créerez vos propres gestionnaires de contexte en utilisant deux méthodes différentes : une approche basée sur une fonction et une approche basée sur une classe.

L'instruction with

Dans cette étape, vous apprendrez à utiliser l'instruction with avec des gestionnaires de contexte (context managers) tels que les objets fichier. Un gestionnaire de contexte est un objet qui est notifié lorsque le contexte (un bloc de code) commence et se termine. L'instruction with gère ce processus de notification automatiquement.

Par exemple, les objets fichier sont des gestionnaires de contexte. Lorsque le bloc with est terminé, l'objet fichier est automatiquement fermé, même si des erreurs surviennent dans le bloc. Cela prévient la perte de données et les fuites de ressources.

Note : Si vous n'êtes pas familier avec l'utilisation de WebIDE (similaire à VS Code), veuillez vous familiariser avec cela lors de ce lab.

Voyons cela en action. Dans l'explorateur de fichiers à gauche, ouvrez le fichier main.py. Copiez et collez le code suivant dedans. Ce code va d'abord créer un fichier et y écrire, puis lire son contenu, le tout en utilisant l'instruction with.

## Nous allons créer un fichier pour démontrer l'instruction 'with'.
## Premièrement, écrivons du contenu dans un fichier.
with open('my_file.txt', 'w') as f:
    f.write('This is a test file.')

## Maintenant, lisons-le à nouveau en utilisant un gestionnaire de contexte.
## Le fichier est automatiquement fermé lors de la sortie du bloc 'with'.
with open('my_file.txt') as f:
    file_contents = f.read()
    print(file_contents)

## Le fichier est automatiquement fermé ici, même si une erreur s'est produite.
print("\nFile has been read and closed.")

Exécutez maintenant le script depuis le terminal pour voir la sortie.

python3 main.py

Vous devriez voir la sortie suivante, confirmant que le fichier a été écrit et lu avec succès. L'instruction with garantit que my_file.txt est correctement fermé après les opérations d'écriture et de lecture.

This is a test file.

File has been read and closed.

L'utilisation d'une instruction with est la manière recommandée de gérer des ressources telles que des fichiers ou des connexions réseau, car elle rend votre code plus propre et plus sûr.

Écrire votre propre gestionnaire de contexte

Dans cette étape, vous découvrirez comment créer un gestionnaire de contexte personnalisé en utilisant une fonction générateur et le décorateur @contextlib.contextmanager. C'est une manière concise de créer des gestionnaires de contexte simples.

Le code avant l'instruction yield s'exécute lors de l'entrée dans le bloc with (la logique de configuration), et le code après l'instruction yield s'exécute lors de sa sortie (la logique de nettoyage). La valeur qui est produite par yield peut être assignée à une variable en utilisant le mot-clé as dans l'instruction with.

Ouvrez le fichier function_cm.py depuis l'explorateur de fichiers. Copiez le code suivant dans le fichier.

## Gestionnaire de contexte basé sur une fonction utilisant le décorateur contextlib
import contextlib

@contextlib.contextmanager
def context_manager(num):
    print('Enter')  ## Le code avant yield s'exécute lors de __enter__
    yield num + 1   ## La valeur produite devient la variable 'cm'
    print('Exit')    ## Le code après yield s'exécute lors de __exit__

with context_manager(2) as cm:  ## cm reçoit la valeur produite (3)
    print('Right in the middle with cm = {}'.format(cm))

Maintenant, exécutez le script dans le terminal.

python3 function_cm.py

Vous verrez la sortie suivante. Remarquez l'ordre d'exécution : le code avant yield s'exécute en premier, puis le code à l'intérieur du bloc with, et enfin le code après yield.

Enter
Right in the middle with cm = 3
Exit

Cette approche est très utile pour créer des contextes temporaires, tels que la configuration et la suppression d'une connexion à une base de données ou la modification temporaire d'un paramètre.

Gestionnaire de contexte basé sur une classe

Dans cette étape, vous allez implémenter un gestionnaire de contexte sous forme de classe. Cette approche offre plus de contrôle et convient aux scénarios plus complexes. Pour créer un gestionnaire de contexte basé sur une classe, vous devez définir deux méthodes spéciales : __enter__ et __exit__.

  • __enter__ : Cette méthode est appelée lorsque l'instruction with est entrée. Elle doit effectuer la logique de configuration (setup logic). Sa valeur de retour est assignée à la variable suivant as, si elle est fournie.
  • __exit__ : Cette méthode est appelée lorsque le bloc with est quitté, que ce soit normalement ou à la suite d'une exception. Elle doit effectuer la logique de nettoyage (cleanup logic).

Créons-en un. Ouvrez le fichier class_cm.py et copiez le code suivant à l'intérieur.

## Gestionnaire de contexte basé sur une classe : implémentation des méthodes __enter__ et __exit__
class ContextManager:
    def __enter__(self, *args, **kwargs):  ## Appelée lors de l'entrée dans le bloc 'with'
        print("--enter--")
        return self  ## Peut retourner l'objet à utiliser comme variable 'as'

    def __exit__(self, *args):  ## Appelée lors de la sortie du bloc 'with'
        print("--exit--")

with ContextManager():  ## Appelle __enter__, puis __exit__ une fois terminé
    print("test")

Exécutez le script depuis le terminal.

python3 class_cm.py

Le résultat démontre le flux de contrôle. La méthode __enter__ est appelée en premier, suivie du code à l'intérieur du bloc with, et enfin, la méthode __exit__ est appelée pour le nettoyage.

--enter--
test
--exit--

L'approche basée sur une classe est puissante car elle vous permet d'encapsuler une logique complexe de configuration et de démontage (setup and teardown logic) au sein d'un objet unique et réutilisable.

Résumé

Félicitations pour avoir terminé ce laboratoire ! Vous avez appris à gérer efficacement les ressources en Python à l'aide des gestionnaires de contexte (context managers).

Vous avez commencé par l'instruction courante with pour la gestion sécurisée des fichiers. Ensuite, vous êtes passé à la création de vos propres gestionnaires de contexte personnalisés en utilisant deux méthodes différentes :

  • Une approche basée sur une fonction avec le décorateur @contextlib.contextmanager, qui est excellent pour les tâches simples de configuration et de nettoyage (setup and teardown).
  • Une approche basée sur une classe en implémentant les méthodes __enter__ et __exit__, qui est idéale pour une gestion des ressources plus complexe.

Ces compétences sont cruciales pour écrire un code Python propre, fiable et efficace qui gère correctement les ressources.