Menu
Coddy logo textTech

Gestores de contexto

Parte de la sección Object Oriented Programming del Journey de Python de Coddy — lección 41 de 64.

Los gestores de contexto permiten asignar y liberar recursos precisamente cuando es necesario. Aseguran una limpieza adecuada incluso si ocurren errores.

Aquí está el ejemplo más común usando la sentencia with:

with open('example.txt', 'w') as file:
    file.write('Hello, world!')
# El archivo se cierra automáticamente aquí

El archivo se cierra automáticamente después del bloque, incluso si ocurre una excepción.

Crea tu propio gestor de contexto implementando los métodos __enter__ y __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  # No suprimir excepciones

Usa tu gestor de contexto personalizado:

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

Salida:

Entering the context
Inside the context
Exiting the context

Crea un administrador de contexto más práctico para conexiones de base de datos:

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...")

Manejar excepciones en gestores de contexto:

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  # No suprimir la excepción

with SafeContext():
    print("Working with resources")
    # raise ValueError("Something went wrong")  # Descomentar para probar

Salida:

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

El método __exit__ recibe tres parámetros:

  • exc_type: Tipo de excepción (o None)
  • exc_val: Valor de la excepción (o None)
  • exc_tb: Traceback de la excepción (o None)

Punto clave: Los gestores de contexto utilizan los métodos __enter__ y __exit__ para gestionar recursos. La sentencia with llama automáticamente a estos métodos, asegurando una configuración y limpieza adecuadas. Esto es especialmente útil para archivos, conexiones a bases de datos y otros recursos que requieren una limpieza garantizada.

challenge icon

Desafío

Fácil

En este desafío, implementarás una clase de gestor de contexto que mide el tiempo transcurrido entre la entrada y la salida de un bloque de contexto.

  • timer.py - Contiene la implementación de la clase Timer (este es el archivo que editarás)
  • driver.py - Contiene casos de prueba exhaustivos (no modificar)

Implementa el gestor de contexto Timer en timer.py siguiendo los comentarios TODO. La clase debe:

  1. Registrar el tiempo de inicio al entrar en un contexto
  2. Registrar el tiempo de finalización al salir
  3. Calcular y mostrar el tiempo transcurrido

Hoja de referencia

Los gestores de contexto asignan y liberan recursos precisamente cuando es necesario, asegurando una limpieza adecuada incluso si ocurren errores.

Utilice la sentencia with para la gestión automática de recursos:

with open('example.txt', 'w') as file:
    file.write('Hello, world!')
# El archivo se cierra automáticamente aquí

Cree gestores de contexto personalizados implementando los métodos __enter__ y __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  # No suprimir excepciones

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

El método __exit__ recibe tres parámetros:

  • exc_type: Tipo de excepción (o None)
  • exc_val: Valor de la excepción (o None)
  • exc_tb: Traceback de la excepción (o None)

Maneje excepciones en los gestores de contexto:

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  # No suprimir la excepción

Pruébalo tú mismo

from timer import Timer
import time

# Manejador de casos de prueba
test_case = input()

if test_case == "basic_test":
    # Prueba de funcionalidad básica
    with Timer():
        # Simular algo de trabajo
        time.sleep(2)  # Esto hace que el programa espere 2 segundos

elif test_case == "nested_contexts":
    # Probar gestores de contexto anidados
    with Timer():
        time.sleep(1)
        with Timer():
            time.sleep(1)

elif test_case == "exception_handling":
    # Probar el manejo de excepciones dentro del contexto
    try:
        with Timer():
            time.sleep(1)
            raise ValueError("Test exception")
    except ValueError as e:
        print(f"Caught exception: {e}")

elif test_case == "zero_sleep":
    # Probar con un tiempo de espera mínimo
    with Timer():
        time.sleep(0.001)

elif test_case == "multiple_timers":
    # Probar múltiples temporizadores en secuencia
    with Timer():
        time.sleep(1)
    
    with Timer():
        time.sleep(0.5)
    
    with Timer():
        time.sleep(2)

elif test_case == "as_decorator":
    # Probar el temporizador en el contexto de una función
    def timed_function():
        with Timer():
            time.sleep(2)
    
    timed_function()

else:
    # Prueba por defecto - funcionalidad básica
    with Timer():
        # Simular algo de trabajo
        time.sleep(2)  # Esto hace que el programa espere 2 segundos
quiz iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Object Oriented Programming