Menu
Coddy logo textTech

Gestionnaires de contexte

Fait partie de la section Programmation orientée objet du Journey Python de Coddy. Leçon 41 sur 64.

Les gestionnaires de contexte vous permettent d’allouer et de libérer des ressources précisément lorsque cela est nécessaire. Ils garantissent un nettoyage approprié même si des erreurs surviennent.

Voici l’exemple le plus courant utilisant l’instruction with :

with open('example.txt', 'w') as file:
    file.write('Hello, world!')
# Le fichier est automatiquement fermé ici

Le fichier est automatiquement fermé après le bloc, même si une exception se produit.

Créez votre propre gestionnaire de contexte en implémentant les méthodes __enter__ et __exit__ :

class MyContext:
    def __enter__(self):
        print("Entering the context")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Exiting the context")
        return False  # Ne pas supprimer les exceptions

Utilisez votre gestionnaire de contexte personnalisé :

with MyContext() as ctx:
    print("Inside the context")

Sortie :

Entering the context
Inside the context
Exiting the context

Créez un gestionnaire de contexte plus pratique pour les connexions à une base de données :

class DatabaseConnection:
    def __init__(self, db_name):
        self.db_name = db_name
        self.connection = None
    
    def __enter__(self):
        print(f"Connecting to {self.db_name}")
        self.connection = f"Connection to {self.db_name}"
        return self.connection
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print(f"Closing connection to {self.db_name}")
        self.connection = None

with DatabaseConnection("users_db") as conn:
    print(f"Using {conn}")
    print("Performing database operations...")

Gérer les exceptions dans les gestionnaires de contexte :

class SafeContext:
    def __enter__(self):
        print("Setting up resources")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Cleaning up resources")
        if exc_type:
            print(f"An exception occurred: {exc_val}")
        return False  # Ne pas supprimer l'exception

with SafeContext():
    print("Working with resources")
    # raise ValueError("Something went wrong")  # Décommentez pour tester

Sortie :

Connecting to users_db
Using Connection to users_db
Performing database operations...
Closing connection to users_db
Setting up resources
Working with resources
Cleaning up resources

La méthode __exit__ reçoit trois paramètres :

  • exc_type : type d’exception (ou None)
  • exc_val : valeur de l’exception (ou None)
  • exc_tb : trace d’exécution de l’exception (ou None)

Point clé : les gestionnaires de contexte utilisent les méthodes __enter__ et __exit__ pour gérer les ressources. L’instruction with appelle automatiquement ces méthodes, garantissant une configuration et un nettoyage appropriés. Cela est particulièrement utile pour les fichiers, les connexions à une base de données et autres ressources nécessitant un nettoyage garanti.

challenge icon

Défi

Facile

Dans ce défi, vous allez implémenter une classe de gestionnaire de contexte qui mesure le temps écoulé entre l’entrée dans un bloc de contexte et sa sortie.

  • timer.py - Contient l’implémentation de la classe Timer (c’est le fichier que vous allez modifier)
  • driver.py - Contient des cas de test complets (ne pas modifier)

Implémentez le gestionnaire de contexte Timer dans timer.py en suivant les commentaires TODO. La classe doit :

  1. Enregistrer l’heure de début lors de l’entrée dans un contexte
  2. Enregistrer l’heure de fin lors de la sortie
  3. Calculer et afficher le temps écoulé

Essayez vous-même

from timer import Timer
import time

# Gestionnaire de cas de test
test_case = input()

if test_case == "basic_test":
    # Test de fonctionnalité de base
    with Timer():
        # Simuler un travail
        time.sleep(2)  # Cela fait attendre le programme pendant 2 secondes

elif test_case == "nested_contexts":
    # Tester les gestionnaires de contexte imbriqués
    with Timer():
        time.sleep(1)
        with Timer():
            time.sleep(1)

elif test_case == "exception_handling":
    # Tester la gestion des exceptions dans le contexte
    try:
        with Timer():
            time.sleep(1)
            raise ValueError("Test exception")
    except ValueError as e:
        print(f"Caught exception: {e}")

elif test_case == "zero_sleep":
    # Tester avec un sleep minimal
    with Timer():
        time.sleep(0.001)

elif test_case == "multiple_timers":
    # Tester plusieurs timers en séquence
    with Timer():
        time.sleep(1)
    
    with Timer():
        time.sleep(0.5)
    
    with Timer():
        time.sleep(2)

elif test_case == "as_decorator":
    # Tester le timer dans un contexte de fonction
    def timed_function():
        with Timer():
            time.sleep(2)
    
    timed_function()

else:
    # Test par défaut - fonctionnalité de base
    with Timer():
        # Simuler un travail
        time.sleep(2)  # Cela fait attendre le programme pendant 2 secondes
quiz iconTestez-vous

Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.

Toutes les leçons de Programmation orientée objet

Entraînez-vous par vous-même : Compilateur Python en ligne