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
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.
Ouvir o resumo desta aula
Um recap de cerca de 2 minutos na voz do Valim, para ouvir no trânsito ou na academia.
Ler a transcrição do resumo
Resumo da aula: Por que o with existe.
Os objetivos desta aula. 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.
Veja o essencial, parte por parte.
O problema do recurso deixado aberto. Recursos abertos (arquivos, conexões, locks) precisam ser fechados depois de usar.
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.
Onde o with já aparece no seu dia a dia. Se um objeto suporta with, use with em vez de fechar à mão.
Esse foi o resumo do essencial. Para se aprofundar, leia a aula completa e responda os exercícios.
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 alcancadaSem 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, garantidoO 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.
| Recurso | O 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 banco | Confirma ou desfaz a transação |
| Cronômetro caseiro | Registra 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.