Gestori di contesto Python: creazione personalizzata con blocchi

Scopri come scrivere gestori di contesto personalizzati in Python. Padroneggia il decoratore del gestore del contesto e i metodi __enter__/__exit__ per la sicurezza delle risorse.

Prova nell'editor

Panoramica

I gestori di contesto sono un meccanismo elegante in Python progettato per gestire l'installazione e lo smontaggio di risorse esterne. Nel software, molte operazioni richiedono coppie di azioni: aprire e chiudere file, connettersi e disconnettersi dai database o acquisire e rilasciare blocchi. Se un programma si arresta in modo anomalo dopo la fase di installazione ma prima della fase di smontaggio, tali risorse rimangono bloccate in memoria. I gestori del contesto garantiscono che le risorse vengano ripulite in modo sicuro in ogni circostanza.

Il modo standard per invocare un gestore di contesto è utilizzare l'istruzione "with". Dietro le quinte, qualsiasi oggetto utilizzato in un'istruzione "with" deve implementare il protocollo Gestore contesto. Questo protocollo consiste di due metodi speciali: `__enter__()` e `__exit__()`. Quando inizia il blocco `with`, viene chiamato `__enter__()` per preparare la risorsa. Quando il blocco `with` termina o solleva un'eccezione, `__exit__()` viene attivato automaticamente, ricevendo informazioni su qualsiasi eccezione sollevata in modo che possa gestire la pulizia o eliminare gli errori.

Per casi d'uso semplici, scrivere una classe con i metodi `__enter__` e `__exit__` può sembrare prolisso. Per semplificare ciò, la libreria standard di Python fornisce il modulo `contextlib`, che presenta il decoratore `@contextmanager`. Questo decoratore ti consente di scrivere una semplice funzione di generazione contenente una singola istruzione `yield`. Il codice prima di "yield" funge da impostazione, il valore restituito funge da risorsa e il codice dopo "yield" rappresenta la pulizia. La padronanza dei gestori di contesto garantisce che le tue applicazioni rimangano esenti da perdite.

Codice e output di esecuzione

Una classe personalizzata che implementa __enter__ e __exit__ per gestire i limiti della registrazione dell'esecuzione.

context_managers.py
Prova nell'editor
class CustomManager:
    def __enter__(self):
        print("--> Resource Setup: Entering the block")
        return "RESOURCE_KEY"

    def __exit__(self, exc_type, exc_value, traceback):
        print("<-- Resource Teardown: Exiting the block")
        if exc_type:
            print(f"Exception Intercepted: {exc_value}")
        return True  # Suppress exceptions

with CustomManager() as res:
    print(f"Working inside block with resource: {res}")
    # Force an error to verify exception handling
    x = 1 / 0
print("Program continues running safely.")
Uscita terminale
--> Resource Setup: Entering the block
Working inside block with resource: RESOURCE_KEY
<-- Resource Teardown: Exiting the block
Exception Intercepted: division by zero
Program continues running safely.

Implementazione passo dopo passo

  • Gestione delle transazioni del database (impegno in caso di successo, rollback in caso di errore)
  • Acquisizione e rilascio dei thread lock nel codice multi-thread
  • Reindirizzamento dell'output standard (stdout) durante gli script di unit test

Domande frequenti

Come posso sopprimere le eccezioni in un gestore di contesto personalizzato?

Restituendo True dal metodo __exit__. Se restituisce True, qualsiasi eccezione sollevata all'interno del blocco verrà soppressa.

Puoi combinare più gestori di contesto in un'unica istruzione?

Sì, puoi separarli con virgole, ad esempio, con open('file1.txt') come f1, open('file2.txt') come f2:.

Argomenti correlati

Risorse Python consigliate

Espandi le tue conoscenze con tutorial interattivi, foglietti illustrativi e confronti di codici correlati.