contextlib: Crie Seu Próprio Context Manager

Publicado:
Atualizado:
PorJeferson Peter
2 min de leitura
Python
Compartilhe este post:

A instrução with é um dos recursos mais expressivos do Python. Ela garante que a lógica de setup e cleanup rode corretamente, mesmo quando ocorrem exceções.

A maioria das pessoas usa isso com arquivos ou conexões de banco de dados. Por baixo dos panos, context managers substituem blocos repetitivos de try/finally por uma abstração mais limpa.

Com contextlib, você pode criar seus próprios context managers e aplicar o mesmo padrão a qualquer problema.


Por Que Context Managers Existem

Sem um context manager, você provavelmente escreveria algo assim:

resource = acquire()
try:
    process(resource)
finally:
    release(resource)

Funciona, mas é repetitivo e fácil de esquecer.

A instrução with formaliza esse padrão. Um context manager define o que acontece ao entrar e ao sair de um bloco de código.


A Abordagem Tradicional: enter e exit

Você pode criar um context manager definindo dois métodos especiais:

class Timer:
    def __enter__(self):
        print("Starting")
        return self

    def __exit__(self, exc_type, exc, tb):
        print("Finished")

Isso é poderoso, mas verboso.

Para casos mais simples, contextlib oferece uma solução mais limpa.


Usando @contextmanager

O decorator @contextmanager permite definir a lógica de setup e cleanup em torno de um único yield.

O código antes do yield roda ao entrar no bloco.
O código depois do yield roda ao sair do bloco, mesmo que uma exceção aconteça.

Exemplo:

import time
import tracemalloc
from contextlib import contextmanager

@contextmanager
def performance_tracker(label="Block"):
    start_time = time.perf_counter()
    tracemalloc.start()
    try:
        yield
    finally:
        elapsed = time.perf_counter() - start_time
        current, peak = tracemalloc.get_traced_memory()
        tracemalloc.stop()
        print(f"{label} took {elapsed:.4f}s | Peak memory: {peak / 1024:.1f} KB")

Uso:

with performance_tracker("Data Processing"):
    data = [x ** 2 for x in range(1_000_000)]

O código dentro do bloco roda normalmente. Quando o bloco termina, o cleanup e o relatório acontecem automaticamente.


Por Que Isso É Poderoso

Context managers customizados permitem:

  • Medir tempo de execução de forma consistente
  • Medir uso de memória
  • Encapsular logs ou métricas
  • Gerenciar estado temporário com segurança
  • Isolar preocupações transversais de forma limpa

Em fluxos com muitos dados, esse padrão ajuda a monitorar transformações sem alterar a lógica principal.

Eu criei um pequeno context de medição de performance em um projeto e acabei usando em tudo. É uma daquelas utilidades que valem a pena na hora.


Boas Práticas

  • Sempre coloque o cleanup dentro de finally
  • Mantenha cada context manager focado em uma responsabilidade
  • Evite embutir lógica de negócio complexa dentro dele
  • Use labels descritivos para observabilidade

Consideração Final

contextlib estende o poder do with para além de arquivos e conexões.

Ao encapsular setup e teardown em uma abstração reutilizável, você reduz repetição e melhora a confiabilidade.

Context managers não são apenas conveniência sintática. Eles são uma forma disciplinada de gerenciar recursos e comportamentos transversais em Python.

Compartilhe este post:
contextlib: Crie Seu Próprio Context Manager | CodeCraftPython