Curso de Python / Ler e gravar texto com with, modos e codificação

Para ler e gravar um arquivo de texto em Python, escolha o modo de abertura e a codificação e use with para fechar o arquivo ao sair do bloco. O modo w apaga o conteúdo anterior ao abrir um arquivo existente: fechar corretamente o arquivo não protege, por si só, os dados que foram substituídos.

Escolher o modo de abertura e a codificação

Modo Finalidade Comportamento
r Ler texto. Exige que o arquivo exista; não o cria.
w Gravar conteúdo novo. Cria o arquivo ou trunca o existente.
a Acrescentar ao final. Preserva o conteúdo existente e cria o arquivo se necessário.
x Criar exclusivamente um arquivo novo. Falha com FileExistsError se o destino já existir.

Esses modos não criam automaticamente as pastas pai ausentes. Confira primeiro a localização do destino, como na prática de caminhos e pastas com pathlib. Um arquivo com o mesmo nome em outra pasta é outro destino; trabalhar sobre o arquivo errado pode parecer um problema de leitura ou de dados.

Uma codificação define a correspondência entre texto e bytes. Para dados em UTF-8, especifique encoding="utf-8" tanto na escrita quanto na leitura, sem depender da configuração padrão do ambiente. Não use errors="ignore" como correção genérica para uma falha: essa opção pode descartar bytes e produzir texto incompleto sem indicar o que foi perdido.

Gravar, acrescentar e ler o arquivo completo

Use uma pasta separada com dados descartáveis. A cada execução, o programa reinicia notes-demo.txt usando w. Salve o código completo em text_files.py, com codificação UTF-8, e execute python text_files.py no terminal dessa pasta, com o ambiente virtual selecionado se houver. Em macOS ou Ubuntu sem ambiente virtual, use python3 text_files.py se esse for o nome do interpretador. Não há dependências externas.

from pathlib import Path

path = Path("notes-demo.txt")
with path.open("w", encoding="utf-8", newline="\n") as f:
    f.write("coffee:3500\n")
    f.write("lunch:8000\n")
with path.open("a", encoding="utf-8") as f:
    f.write("bus:2500\n")
with path.open("r", encoding="utf-8") as f:
    for line in f:
        print(line.rstrip("\n"))

A saída esperada é:

coffee:3500
lunch:8000
bus:2500

O primeiro bloco grava duas linhas, com os rótulos de exemplo coffee e lunch, correspondentes a café e almoço. Ao terminar o bloco, o arquivo é fechado. O segundo bloco abre novamente em modo a e acrescenta a linha bus:2500, correspondente a ônibus. O terceiro abre em modo r, percorre as linhas e imprime o texto.

rstrip("\n") remove a quebra de linha final recebida da leitura, enquanto print() acrescenta sua própria quebra ao exibir cada linha. Sem essa remoção, o terminal mostraria linhas em branco adicionais. Os valores depois de dois-pontos continuam sendo texto nesse programa: não são convertidos nem somados.

No primeiro bloco, newline="\n" mantém as quebras gravadas como LF. O bloco de acréscimo usa a configuração padrão de quebras de linha, que pode converter \n para o formato do sistema. A leitura textual padrão normaliza as quebras reconhecidas. Assim, a saída pode ser igual mesmo quando os bytes de fim de linha do arquivo diferem entre ambientes. Se precisar de um formato uniforme no disco, configure a escrita e o acréscimo de maneira consistente.

Ler por linhas, acompanhar a posição e preservar espaços

read() lê o conteúdo restante a partir da posição atual do arquivo. O laço for line in f processa uma linha por vez e evita carregar todo o conteúdo de uma vez quando isso não é necessário. Depois de alcançar o fim, uma nova leitura retorna uma string vazia; para começar de novo, reabra o arquivo ou use seek(0) quando a operação for suportada.

strip() remove espaços e outros caracteres de espaço em branco das duas pontas, não apenas a quebra de linha. Se espaços fizerem parte dos dados, prefira remover somente os caracteres desejados. No exemplo, a abertura textual padrão traduz os finais de linha reconhecidos para \n, e rstrip("\n") mantém espaços iniciais e finais. Com outras configurações de newline, confirme quais caracteres a leitura realmente entrega.

Um bloco with fecha o objeto de arquivo quando o bloco termina, inclusive quando uma exceção escapa dele após a abertura bem-sucedida. Fora do bloco, tentar ler esse mesmo objeto fechado causa ValueError. Fechar libera o recurso, mas não representa uma transação nem desfaz escritas já realizadas. O tutorial de leitura e escrita de arquivos apresenta esse gerenciamento.

Testar os modos e investigar erros sem ocultar dados

  1. Execute o programa original duas vezes. A saída permanece com três linhas, porque cada execução começa truncando o arquivo em w. Abra o arquivo num editor e confira também seu conteúdo, não apenas o terminal.
  2. Troque somente o primeiro path.open("w", ...) por path.open("a", ...), mantendo o arquivo criado antes. Ao executar de novo, serão acrescentadas mais três linhas: as três anteriores permanecem e a saída passa a ter seis linhas. Outra execução acrescenta mais três.
  3. Restaure o primeiro modo para w e execute. O arquivo volta às três linhas originais. Esse retorno ao estado inicial sobrescreve os dados da prática, portanto faça a comparação somente no destino descartável indicado.
  4. Para comparar preservação de espaços, altere temporariamente o primeiro texto gravado para " coffee:3500 \n". A remoção de apenas \n conserva os espaços; usar strip() nessa linha os eliminaria. Restaure o texto original após observar a diferença.

Para FileNotFoundError, confira o caminho resolvido e se a pasta pai existe. Para UnicodeDecodeError, identifique a codificação real dos dados antes de escolher como convertê-los. Para PermissionError, investigue permissões e bloqueios por outros programas; apontar para uma pasta em vez de um arquivo também pode gerar um erro cujo tipo varia conforme o sistema. Não converta indiscriminadamente todas essas falhas numa string vazia, pois isso confunde ausência de dados com falha de acesso.

Com arquivos importantes, preserve uma cópia e considere gravar num arquivo temporário separado, validar o conteúdo e só então substituir o destino conforme a política definida. Se uma escrita falhar depois da abertura em w, o original pode já ter sido truncado. A referência de open(), modos e tratamento de codificação permite conferir as opções; o programa ainda precisa decidir quais erros consegue recuperar e como preservar o conteúdo anterior.