Protocolo __enter__ e __exit__
Crie gerenciadores de contexto usando o protocolo dunder.
Protocolo __enter__ e __exit__ é uma aula grátis de Python Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Python Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Python Academy inclui 4 aulas no total.
O protocolo de gerenciador de contexto
Qualquer objeto que defina __enter__ e __exit__ é um gerenciador de contexto e pode ser usado com 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")Valor de retorno de __enter__
__enter__ é chamado no início do bloco with. Seu valor de retorno é associado à variável depois de 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) # 42Argumentos de __exit__
__exit__(exc_type, exc_val, exc_tb) recebe informações sobre a exceção se um erro tiver ocorrido. Se não houver exceção, os três valores serão 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") # suppressedSuprimindo exceções
Retorne True de __exit__ para suprimir a exceção. Retorne False (ou não retorne nada) para permitir que ela seja propagada.
class Ignore:
def __enter__(self): return self
def __exit__(self, *args): return True # swallow all exceptions
with Ignore():
1 / 0
print("continues here")Um exemplo de conexão com banco de dados
Um caso de uso clássico: adquirir uma conexão ao entrar, confirmar ou desfazer a transação e fechar ao sair.
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 FalseUm gerenciador de contexto Timer
Meça o tempo decorrido registrando o início em __enter__ e calculando a diferença em __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))Aninhando gerenciadores de contexto
Vários gerenciadores de contexto podem ser combinados em uma única linha de with.
with open("in.txt") as src, open("out.txt", "w") as dst:
dst.write(src.read())Gerenciadores reutilizáveis vs de uso único
Os gerenciadores de contexto cujo __enter__ aloca um recurso novo a cada vez são reutilizáveis. Aqueles que esgotam um estado interno (como um bloqueio mantido apenas uma vez) podem não ser.
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__ (assíncronos)
Para gerenciadores de contexto assíncronos, defina corrotinas __aenter__ e __aexit__ e use 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:
# ...Envolvendo objetos de arquivo
Os objetos de arquivo do Python já implementam o protocolo de gerenciador de contexto — nunca chame f.close() manualmente.
with open("data.txt", "r") as f:
data = f.read()
# file is closed here automatically
print(f.closed) # TrueImplementando um Lock
Bloqueios de threads são gerenciadores de contexto: __enter__ adquire o bloqueio e __exit__ o libera.
import threading
lock = threading.Lock()
def update_shared():
with lock:
# critical section
passVerificação rápida
O que __exit__ deve retornar para suprimir uma exceção?
Recapitulação
Implemente __enter__ e __exit__ para criar gerenciadores de contexto. Retorne o recurso de __enter__ e trate a limpeza e a supressão de exceções em __exit__.
Perguntas Frequentes
A aula “Protocolo __enter__ e __exit__” é grátis?
Sim — o texto completo de “Protocolo __enter__ e __exit__” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Python Academy, atualize para CoddyKit PRO. O curso de Python Academy inclui 4 aulas no total.
O que vou aprender em “Protocolo __enter__ e __exit__”?
Crie gerenciadores de contexto usando o protocolo dunder. Você pratica Python Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Python Academy?
Nenhuma experiência prévia é necessária. Python Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Protocolo __enter__ e __exit__”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Python Academy?
Sim. Cada aula de Python Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- A instrução with em profundidade
- Protocolo __enter__ e __exit__
- contextlib: @contextmanager
- Padrões práticos de gerenciadores de contexto