Menu
Coddy logo textTech

Context manager

Fa parte della sezione Programmazione orientata agli oggetti del percorso Python di Coddy. Lezione 41 di 64.

I gestori di contesto ti permettono di allocare e rilasciare risorse esattamente quando serve. Garantiscono una corretta pulizia anche se si verificano errori.

Ecco l'esempio più comune che utilizza l'istruzione with:

with open('example.txt', 'w') as file:
    file.write('Hello, world!')
# Il file viene chiuso automaticamente qui

Il file viene chiuso automaticamente dopo il blocco, anche se si verifica un'eccezione.

Crea il tuo gestore di contesto implementando i metodi __enter__ e __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  # Non sopprimere le eccezioni

Usa il tuo gestore di contesto personalizzato:

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

Output:

Entering the context
Inside the context
Exiting the context

Crea un gestore di contesto più pratico per le connessioni al database:

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

Gestire le eccezioni nei gestori di contesto:

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  # Non sopprimere l'eccezione

with SafeContext():
    print("Working with resources")
    # raise ValueError("Something went wrong")  # Rimuovi il commento per fare una prova

Output:

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

Il metodo __exit__ riceve tre parametri:

  • exc_type: tipo di eccezione (o None)
  • exc_val: valore dell'eccezione (o None)
  • exc_tb: traceback dell'eccezione (o None)

Punto chiave: i gestori di contesto usano i metodi __enter__ e __exit__ per gestire le risorse. L'istruzione with chiama automaticamente questi metodi, garantendo una corretta configurazione e pulizia. Questo è particolarmente utile per i file, le connessioni al database e altre risorse che richiedono una pulizia garantita.

challenge icon

Sfida

Facile

In questa sfida, implementerai una classe gestore di contesto che misura il tempo trascorso tra l'ingresso e l'uscita da un blocco di contesto.

  • timer.py - Contiene l'implementazione della classe Timer (questo è il file che modificherai)
  • driver.py - Contiene casi di test completi (non modificare)

Implementa il gestore di contesto Timer in timer.py seguendo i commenti TODO. La classe deve:

  1. Registrare l'ora di inizio quando si entra in un contesto
  2. Registrare l'ora di fine quando si esce
  3. Calcolare e visualizzare il tempo trascorso

Provalo tu

from timer import Timer
import time

# Gestore dei casi di test
test_case = input()

if test_case == "basic_test":
    # Test delle funzionalità di base
    with Timer():
        # Simula un po' di lavoro
        time.sleep(2)  # Questo fa attendere il programma per 2 secondi

elif test_case == "nested_contexts":
    # Test dei gestori di contesto annidati
    with Timer():
        time.sleep(1)
        with Timer():
            time.sleep(1)

elif test_case == "exception_handling":
    # Test della gestione delle eccezioni all'interno del contesto
    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 con una pausa minima
    with Timer():
        time.sleep(0.001)

elif test_case == "multiple_timers":
    # Test di più timer in sequenza
    with Timer():
        time.sleep(1)
    
    with Timer():
        time.sleep(0.5)
    
    with Timer():
        time.sleep(2)

elif test_case == "as_decorator":
    # Test del timer nel contesto di una funzione
    def timed_function():
        with Timer():
            time.sleep(2)
    
    timed_function()

else:
    # Test predefinito - funzionalità di base
    with Timer():
        # Simula un po' di lavoro
        time.sleep(2)  # Questo fa attendere il programma per 2 secondi
quiz iconMettiti alla prova

Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.

Tutte le lezioni di Programmazione orientata agli oggetti

Esercitati da solo: Compilatore Python online