Python/Avançado/Context Managers
Python⏱ ~2 min de leitura

Context Managers

with, __enter__, __exit__ e contextlib

Context managers são objetos que definem o protocolo de entrada e saída de um bloco with. Quando o bloco termina (com ou sem exceção), o método __exit__ é chamado automaticamente, garantindo limpeza de recursos como arquivos, conexões e locks.

__enter__ é chamado ao entrar no with e retorna o objeto disponível na cláusula as. __exit__ recebe informações sobre qualquer exceção ocorrida — se retornar True, a exceção é suprimida; se retornar None/False, a exceção se propaga.

contextlib.contextmanager permite criar context managers com generators usando yield, sem precisar de uma classe completa.

Exemplo.java
import contextlib
import time

# Context manager com classe
class Temporizador:
    def __enter__(self):
        self.inicio = time.time()
        return self  # disponível no "as"

    def __exit__(self, tipo_exc, valor_exc, tb):
        self.duracao = time.time() - self.inicio
        print(f"Durou {self.duracao:.4f}s")
        return False  # não suprimir exceções

with Temporizador() as t:
    time.sleep(0.1)
# Durou 0.1001s

# Context manager com generator
@contextlib.contextmanager
def conexao_db(url):
    print(f"Conectando a {url}")
    conn = {"url": url, "ativo": True}
    try:
        yield conn  # ponto de pausa — executa o bloco with
    finally:
        conn["ativo"] = False
        print("Conexão fechada")

with conexao_db("postgresql://localhost/db") as conn:
    print(f"Usando: {conn}")

# suppress — suprimir exceções específicas
with contextlib.suppress(FileNotFoundError):
    open("arquivo_que_nao_existe.txt")
# Sem erro! A exceção é suprimida

# Múltiplos context managers em um with
with open("a.txt") as f1, open("b.txt") as f2:
    dados = f1.read() + f2.read()
💡 Dica pro

Use @contextmanager para context managers simples e classe completa quando precisar de estado persistente ou herança.

Recompensa+40 XP+exercícios