Exercice 01 : Gestionnaire de Contexte pour les Connexions à une Base de Données
Objectif
Cet exercice a pour but de vous faire créer un gestionnaire de contexte simple en utilisant une classe pour simuler la gestion d'une connexion à une base de données. Cela illustre comment with peut garantir que les ressources sont correctement ouvertes et fermées.
Contexte
Lorsque vous travaillez avec des bases de données, il est crucial de s'assurer que chaque connexion ouverte est correctement fermée à la fin, même si des erreurs se produisent. Un gestionnaire de contexte est la solution parfaite pour ce problème.
Vous allez simuler ce comportement en créant une classe DatabaseConnection qui pourra être utilisée avec l'instruction with.
Énoncé
-
Créez un nouveau fichier Python nommé
db_context_manager.py. -
Définissez la classe
DatabaseConnection.- Son constructeur
__init__doit accepter un paramètredb_name(le nom de la base de données). - Dans le constructeur, stockez
db_nameet initialisez un attributself.is_connectedàFalse.
- Son constructeur
-
Implémentez la méthode
__enter__.- Cette méthode simule l'ouverture de la connexion.
- Elle doit afficher un message comme
f"Connecting to database '{self.db_name}'...". - Elle doit passer
self.is_connectedàTrue. - Elle doit se retourner elle-même (
return self) pour que l'objet puisse être utilisé dans le blocwith(avec la syntaxeas).
-
Implémentez la méthode
__exit__.- Cette méthode simule la fermeture de la connexion.
- Elle doit afficher un message comme
f"Closing connection to database '{self.db_name}'...". - Elle doit passer
self.is_connectedàFalse. - Elle ne doit pas supprimer les exceptions (elle doit donc retourner
NoneouFalseimplicitement).
-
Ajoutez une méthode
queryà votre classe.- Elle prend un argument
sql_query. - Elle doit vérifier si
self.is_connectedestTrue. - Si oui, elle affiche
f"Executing query: '{sql_query}'". - Si non, elle lève une
ConnectionErroravec un message clair.
- Elle prend un argument
-
Testez votre gestionnaire de contexte : a. Utilisez une instruction
withpour créer une connexion à une base de données "test_db". b. À l'intérieur du blocwith, appelez la méthodequeryavec une requête SQL de votre choix. c. Après le blocwith, essayez d'appeler à nouveau la méthodequerysur l'objet connexion pour vérifier que la connexion est bien fermée et qu'une erreur est levée. Utilisez un bloctry...exceptpour attraper cetteConnectionError.
Résultat Attendu
Connecting to database 'test_db'...
Executing query: 'SELECT * FROM users'
Closing connection to database 'test_db'...
---
Trying to query after closing connection...
Error: Not connected to the database.
Cliquez ici pour voir un exemple de code de solution
# db_context_manager.py
class DatabaseConnection:
def __init__(self, db_name):
self.db_name = db_name
self.is_connected = False
def __enter__(self):
"""Opens the database connection."""
print(f"Connecting to database '{self.db_name}'...")
self.is_connected = True
return self
def __exit__(self, exc_type, exc_val, exc_tb):
"""Closes the database connection."""
print(f"Closing connection to database '{self.db_name}'...")
self.is_connected = False
# We don't handle exceptions, so we let them propagate by returning None/False.
def query(self, sql_query):
"""Executes a SQL query."""
if not self.is_connected:
raise ConnectionError("Not connected to the database.")
print(f"Executing query: '{sql_query}'")
# --- Testing ---
# 1. Normal usage with the 'with' statement
with DatabaseConnection("test_db") as db:
db.query("SELECT * FROM users")
print("---")
# 2. Trying to use the connection outside the 'with' block
print("Trying to query after closing connection...")
# We need to re-create the object to test this, as 'db' from the previous
# block still exists but is in a "closed" state.
db_instance = DatabaseConnection("another_db")
# Let's manually enter and exit to simulate the state after a 'with' block
db_instance.__enter__()
db_instance.__exit__(None, None, None) # Manually close it
try:
db_instance.query("SELECT * FROM products")
except ConnectionError as e:
print(f"Error: {e}")