lettura normale

Context Manager in Python

Un context manager è un costrutto che ti permette di gestire automaticamente risorse che implementano due metodi speciali: `__enter__()` e `__exit__()`.

  • `__enter__(self)`
    Questo metodo viene eseguito all'inizio del blocco `with`. Serve per acquisire le risorse necessarie e può restituire un valore che sarà assegnato alla variabile dopo `as`.
  • `__exit__(self, exc_type, exc_val, exc_tb)`
    Questo metodo viene eseguito alla fine del blocco `with`, sia che il blocco termini normalmente sia che termini a causa di un'eccezione. Serve per rilasciare le risorse acquisite.

    I parametri `exc_type`, `exc_val`, ed `exc_tb` forniscono informazioni sull'eccezione che potrebbe essere stata sollevata. Se il metodo ritorna `True`, l'eccezione viene soppressa.

Questi metodi vengono rispettivamente chiamati all'inizio e alla fine del contesto dall'istruzione `with`.

Puoi definire un context manager con le classi oppure con le funzioni.

A cosa servono i context manager? Sono molto utili per lavorare con le risorse che devono essere acquisite e rilasciate, come file, connessioni di rete, o blocchi di sincronizzazione. I context manage, perché ti assicurano che vengano sempre rilasciate correttamente, indipendentemente da come termina il blocco di codice associato.

Un esempio

Ecco un esempio di context manager implementato come classe tramite l'istruzione with:

class MyContextManager:
    def __enter__(self):
        print("Entering the context")
        # Codice per acquisire la risorsa
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("Exiting the context")
        # Codice per rilasciare la risorsa
        if exc_type:
            print(f"An exception occurred: {exc_val}")
        return True  # Ritorna True per sopprimere l'eccezione, False altrimenti

with MyContextManager() as manager:
    # Codice all'interno del contesto
 
   print("Inside the context")
 

In questo esempio abbiamo definito la classe 'MyContextManager()' con i metodi __enter__ e __exit__.

Quando chiamiamo la classe con il costrutto with, viene eseguito prima il metodo __enter__, poi il contenuto all'interno del contesto e infine il metodo __exit__

Questo è l'output del programma:

Entering the context
Inside the context
Exiting the context

Puoi realizzare i context manager anche con le funzioni

Ecco un altro esempio di context manager realizzato con una funzione.

In questo caso abbiamo ottenuto un context manager decorando la funzione con @contextmanager

from contextlib import contextmanager

@contextmanager
def my_context_manager():
    print("Entering the context")
    try:
        yield
        print("Inside the context")
    finally:
        print("Exiting the context")

with my_context_manager():
   # Codice all'interno del contesto
   print("Doing something inside the context")
 

In questo caso il metodo __enter__ esegue il codice che precede l'istruzione yield.

Il metodo __exit__, invece, esegue il codice che segue l'istruzione yield.

Il risultato in output è il seguente:

Entering the context
Doing something inside the context
Inside the context
Exiting the context

Nota che in caso di errore il metodo __exit__ non viene eseguito ma la clausola finally viene eseguita in ogni caso.

Quindi, se vuoi che il metodo __exit__ sia sempre eseguito, lo devi porre dentro la clausola finally.




Se qualcosa non ti è chiaro, scrivi la tua domanda nei commenti.




FacebookTwitterLinkedinLinkedin