0Pricing
Python Academy · Lezione

Protocollo __enter__ e __exit__

Costruisca context manager utilizzando il protocollo dunder.

Protocollo __enter__ e __exit__ è una lezione Python Academy gratuita su CoddyKit. Questa è la lezione 2 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Python Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Python Academy include 4 lezioni in totale.

Il protocollo dei gestori di contesto

Qualsiasi oggetto che definisce __enter__ e __exit__ è un gestore di contesto e può essere utilizzato con with.

class Managed:
    def __enter__(self):
        print("entering")
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        print("exiting")
        return False

with Managed() as m:
    print("inside")

Valore restituito da __enter__

__enter__ viene chiamato all'inizio del blocco with. Il suo valore restituito viene assegnato alla variabile dopo as.

class Resource:
    def __enter__(self):
        self.value = 42
        return self  # bound to 'r'

    def __exit__(self, *args):
        self.value = None
        return False

with Resource() as r:
    print(r.value)  # 42

Argomenti di __exit__

__exit__(exc_type, exc_val, exc_tb) riceve le informazioni sull'eccezione se si è verificato un errore. Se non si verifica alcuna eccezione, tutti e tre sono None.

class Safe:
    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is ValueError:
            print(f"Suppressed ValueError: {exc_val}")
            return True   # suppress the exception
        return False      # re-raise anything else

with Safe():
    raise ValueError("oops")  # suppressed

Sopprimere le eccezioni

Restituisca True da __exit__ per sopprimere l'eccezione. Restituisca False (o non restituisca nulla) per lasciarla propagare.

class Ignore:
    def __enter__(self): return self
    def __exit__(self, *args): return True  # swallow all exceptions

with Ignore():
    1 / 0

print("continues here")

Esempio di connessione al database

Un caso d'uso classico: acquisire una connessione all'ingresso, eseguire il commit o il rollback e chiuderla all'uscita.

class DBConn:
    def __enter__(self):
        self.conn = connect_db()
        return self.conn

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type:
            self.conn.rollback()
        else:
            self.conn.commit()
        self.conn.close()
        return False

Un gestore di contesto per misurare il tempo

Misuri il tempo trascorso registrando l'inizio in __enter__ e calcolando la differenza in __exit__.

import time

class Timer:
    def __enter__(self):
        self.start = time.perf_counter()
        return self

    def __exit__(self, *args):
        self.elapsed = time.perf_counter() - self.start
        print(f"Elapsed: {self.elapsed:.3f}s")
        return False

with Timer():
    sum(range(1_000_000))

Annidare i gestori di contesto

È possibile combinare più gestori di contesto in una singola riga with.

with open("in.txt") as src, open("out.txt", "w") as dst:
    dst.write(src.read())

Gestori riutilizzabili e monouso

I gestori di contesto il cui __enter__ alloca ogni volta una nuova risorsa sono riutilizzabili. Quelli che esauriscono uno stato interno (come un lock mantenuto una sola volta) potrebbero non esserlo.

class Reusable:
    def __enter__(self):
        return []
    def __exit__(self, *a):
        return False

for _ in range(3):
    with Reusable() as lst:
        lst.append(1)
        print(lst)  # [1] each time

__aenter__ e __aexit__ (asincroni)

Per i gestori di contesto asincroni, definisca le coroutine __aenter__ e __aexit__ e utilizzi async with.

class AsyncDB:
    async def __aenter__(self):
        self.conn = await connect()
        return self.conn

    async def __aexit__(self, *args):
        await self.conn.close()

# async with AsyncDB() as conn:
#     ...

Avvolgere gli oggetti file

Gli oggetti file di Python implementano già il protocollo dei gestori di contesto: non chiami mai manualmente f.close().

with open("data.txt", "r") as f:
    data = f.read()
# file is closed here automatically
print(f.closed)  # True

Implementare un lock

I lock dei thread sono gestori di contesto: __enter__ acquisisce il lock, mentre __exit__ lo rilascia.

import threading

lock = threading.Lock()

def update_shared():
    with lock:
        # critical section
        pass

Controllo rapido

Che cosa deve restituire __exit__ per sopprimere un'eccezione?

Riepilogo

Implementi __enter__ e __exit__ per creare gestori di contesto. Restituisca la risorsa da __enter__ e gestisca la pulizia e la soppressione delle eccezioni in __exit__.

Domande Frequenti

La lezione «Protocollo __enter__ e __exit__» è gratuita?

Sì — il testo completo di «Protocollo __enter__ e __exit__» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Python Academy, passa a CoddyKit PRO. Il corso Python Academy include 4 lezioni in totale.

Cosa imparerò in «Protocollo __enter__ e __exit__»?

Costruisca context manager utilizzando il protocollo dunder. Eserciti Python Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Python Academy?

Non è richiesta alcuna esperienza precedente. Python Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 2 di 4.

Quanto tempo richiede la lezione «Protocollo __enter__ e __exit__»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Python Academy?

Sì. Ogni lezione Python Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. L'istruzione with in dettaglio
  2. Protocollo __enter__ e __exit__
  3. contextlib: @contextmanager
  4. Schemi pratici per i context manager
← Torna a Python Academy