Menu
Coddy logo textTech

Gestionnaires de contexte

Fait partie de la section Object Oriented Programming 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 quand 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 survient.

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 aux bases de données :

class DatabaseConnection:
    def __init__(self, db_name):
        self.db_name = db_name
        self.connection = None
    
    def __enter__(self):
        # Connexion à self.db_name
        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):
        # Fermeture de la connexion à self.db_name
        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écommenter 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 : Traceback 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. Ceci est particulièrement utile pour les fichiers, les connexions aux bases de données et d'autres ressources qui nécessitent 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 et la sortie d'un bloc de contexte.

  • timer.py - Contient l'implémentation de la classe Timer (c'est le fichier que vous allez éditer)
  • 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é

Aide-mémoire

Les gestionnaires de contexte allouent et libèrent les ressources précisément quand cela est nécessaire, garantissant un nettoyage approprié même si des erreurs surviennent.

Utilisez l'instruction with pour une gestion automatique des ressources :

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

Créez des gestionnaires de contexte personnalisés 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

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

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 : Traceback de l'exception (ou None)

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

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 au sein du 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":
    # Test avec un sommeil minimal
    with Timer():
        time.sleep(0.001)

elif test_case == "multiple_timers":
    # Tester plusieurs minuteurs 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 minuteur dans le contexte d'une 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 Object Oriented Programming