Skip to main content

ContextLib | Python

  • ContextLib | Python

🧱 O que é contextmanager

O contextmanager é um decorador da biblioteca padrão contextlib que permite criar contextos gerenciados — ou seja, blocos que funcionam com o with, sem precisar criar uma classe com __enter__ e __exit__.

👉 Ele simplifica o uso de recursos que precisam ser abertos e depois fechados com segurança (como arquivos, conexões, locks, etc.).


⚙️ Exemplo Básico

from contextlib import contextmanager

@contextmanager
def abrir_arquivo(caminho, modo):
print("Abrindo arquivo...")
f = open(caminho, modo)
try:
yield f # entrega o recurso para o bloco 'with'
finally:
print("Fechando arquivo...")
f.close()

# Uso
with abrir_arquivo("exemplo.txt", "w") as arquivo:
arquivo.write("Olá, mundo!")

🧩 Explicação:

  • @contextmanager transforma a função em um gerenciador de contexto.
  • Tudo antes do yield é executado ao entrar no contexto.
  • O valor retornado pelo yield é entregue ao as ... no with.
  • O bloco depois do yield (ou no finally) roda ao sair do contexto, mesmo com erro.

🧰 Tratando Exceções Dentro do Contexto

from contextlib import contextmanager

@contextmanager
def exemplo():
print("Entrando no contexto")
try:
yield
except Exception as e:
print(f"Ocorreu erro: {e}")
finally:
print("Saindo do contexto")

with exemplo():
print("Executando algo...")
raise ValueError("Erro simulado")

Saída:

Entrando no contexto
Executando algo...
Ocorreu erro: Erro simulado
Saindo do contexto

🔒 Uso Real: Locks, Conexões e Temporários

import threading
from contextlib import contextmanager

lock = threading.Lock()

@contextmanager
def sincronizado():
lock.acquire()
try:
yield
finally:
lock.release()

with sincronizado():
print("Executando seção crítica com lock.")

🧠 Dica Extra: contextlib.ExitStack

Se precisar gerenciar múltiplos contextos dinamicamente, use:

from contextlib import ExitStack

with ExitStack() as stack:
f1 = stack.enter_context(open("a.txt", "w"))
f2 = stack.enter_context(open("b.txt", "w"))
f1.write("Arquivo A")
f2.write("Arquivo B")

🧾 Resumo Rápido

ElementoFunção
@contextmanagerCria contexto sem precisar de classe
yieldEntrega o recurso ao bloco with
try/finallyGarante limpeza mesmo com erro
ExitStackGerencia vários contextos dinamicamente