Módulo 6 - Context managers e o with

Por que o with existe

9 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026

Velocidade

O que você vai aprender

  • Entender o problema de recursos que precisam ser fechados.
  • Ver como uma exceção pode impedir a limpeza no código sem with.
  • Reconhecer o with como garantia de limpeza aconteça o que acontecer.
  • Comparar o try, finally manual com o with equivalente.

O problema do recurso deixado aberto

Muitos recursos de um programa seguem o mesmo ritual: você abre, usa e fecha. Um arquivo é o exemplo mais comum, mas a mesma lógica vale para conexões de rede, bloqueios entre threads e transações de banco de dados. O perigo mora no fechar. Se você esquece de fechar um arquivo, ou se uma exceção interrompe o programa antes da linha que fecha, o recurso fica preso. Arquivos abertos demais esgotam um limite do sistema; locks não liberados travam outras threads.

# Frágil: se processar() lançar uma excecao,
# a linha arquivo.close() nunca roda e o arquivo fica aberto.
arquivo = open("dados.txt")
dados = arquivo.read()
processar(dados)      # e se isto falhar?
arquivo.close()       # esta linha pode nunca ser alcancada

Sem proteção, uma exceção no meio impede o fechamento do arquivo.

O trecho acima parece correto, e funciona enquanto tudo dá certo. O problema aparece no dia ruim: se processar levantar uma exceção, o Python abandona o fluxo normal e pula direto para o tratamento de erro mais próximo, sem passar pela linha do close. O arquivo fica aberto até o coletor de lixo eventualmente cuidar dele, o que é imprevisível. Confiar na sorte para fechar recursos é uma fonte clássica de bugs que só aparecem sob carga.

Da solução manual para o with

A solução tradicional é o try com finally: você coloca o uso do recurso no try e o fechamento no finally, que roda sempre, com erro ou sem. Funciona, mas é verboso e fácil de esquecer. O with foi criado exatamente para embutir esse padrão. Quando você escreve with open(...) as arquivo, o Python garante que o arquivo será fechado ao sair do bloco, não importa se a saída foi normal ou por uma exceção. É o mesmo finally, embutido e legível.

Com try, finally (manual)

  • arquivo = open("dados.txt")
  • try: usar o arquivo
  • finally: arquivo.close()
  • Verboso e fácil de esquecer o finally

Com with (embutido)

  • with open("dados.txt") as arquivo:
  • usar o arquivo
  • O fechamento é automático ao sair
  • Curto, legível e à prova de esquecimento
# Robusto e pythônico: o arquivo fecha ao sair do bloco,
# mesmo que processar() lance uma excecao.
with open("dados.txt") as arquivo:
    dados = arquivo.read()
    processar(dados)
# aqui o arquivo ja esta fechado, garantido

O with garante o fechamento na saída do bloco, com erro ou sem erro.

A diferença não é só estética. O with transforma uma promessa que depende da disciplina do programador em uma garantia da própria linguagem. Por isso a recomendação é clara: sempre que um objeto oferecer suporte a with, use with. E quando você criar seus próprios recursos, arquivos temporários, conexões, bloqueios, vale torná-los compatíveis com with, para que quem os use ganhe a mesma garantia de limpeza. As próximas aulas mostram exatamente como fazer isso.

Onde o with já aparece no seu dia a dia

Você já usa context managers mesmo sem ter reparado. Abrir arquivo com with open é o caso mais comum. Mas a biblioteca padrão usa o mesmo mecanismo em vários lugares: um Lock de threads é usado com with para garantir a liberação; conexões de banco de dados oferecem with para confirmar ou desfazer uma transação; e há utilitários prontos no módulo contextlib. Reconhecer o padrão ajuda a entender o que aquele with está de fato garantindo em cada caso.

RecursoO que o with garante ao sair
Arquivo (open)Fecha o arquivo e libera o descritor
Lock (threading.Lock)Libera o bloqueio para outras threads
Conexão de bancoConfirma ou desfaz a transação
Cronômetro caseiroRegistra o tempo decorrido do bloco

O mesmo mecanismo de with, aplicado a recursos diferentes.

Teste rápido

Qual é a principal garantia que o comando with oferece?

Perguntas frequentes

O with impede que exceções aconteçam no bloco?
Não. As exceções continuam podendo acontecer normalmente dentro do bloco with. O que ele garante é que a limpeza do recurso vai rodar mesmo quando uma exceção ocorre, antes de o erro subir. Pense nele como um finally embutido, não como um try, except que trata o erro. Tratar a exceção ainda é responsabilidade do seu código.
Preciso do with se meu código nunca lança exceção?
Vale usar mesmo assim. Você raramente tem certeza de que nada vai falhar, e o with é mais curto e claro que o fechamento manual. Além disso, ele deixa a intenção explícita: este recurso vive só dentro deste bloco. É um bom hábito que evita a categoria inteira de bugs de recurso deixado aberto.
Qual a diferença entre with e try, finally?
São equivalentes no efeito: ambos garantem que uma limpeza aconteça na saída. O with é açúcar sintático que embute o try, finally de forma legível e reutilizável, delegando a limpeza ao objeto. O try, finally é mais geral e serve quando não há um context manager pronto para o que você precisa.
Posso usar mais de um recurso no mesmo with?
Pode. Você separa por vírgula: with open("a") as fa, open("b") as fb: usa os dois no mesmo bloco, e ambos são fechados na saída, na ordem inversa. Para muitos recursos ou uma quantidade que varia, existe o contextlib.ExitStack, que você vê mais adiante neste módulo.
O que acontece se eu esquecer de fechar um arquivo sem with?
O arquivo fica aberto até o coletor de lixo eventualmente fechá-lo, o que é imprevisível. Em programas que abrem muitos arquivos, isso esgota o limite de descritores do sistema operacional e gera erros. Além disso, dados escritos podem não ir para o disco na hora certa. Por tudo isso, o with é a forma recomendada.

Fontes

Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.