Escrever e Criar Arquivos em Python
Aprenda a escrever arquivos em Python: write(), writelines(), modo append, escrita binária, pathlib, codificação e padrões seguros com blocos with.
Escrever arquivos é uma das operações de E/S mais fundamentais em Python. Seja para salvar a saída de um programa, persistir configurações, exportar dados para CSV ou registrar eventos, você precisa de uma maneira confiável de criar e atualizar arquivos. Este capítulo aborda todas as abordagens que Python oferece: write(), writelines(), modo append, escrita binária, tratamento de quebras de linha, codificação de caracteres, a API moderna pathlib e padrões para escrever arquivos com segurança sem perda de dados.
Abrindo um Arquivo para Escrita
Toda operação de escrita em arquivo começa com a função embutida open(). O segundo argumento — o modo — controla o que acontece quando você abre o arquivo:
| Modo | Significado | Arquivo existe | Arquivo ausente |
|---|---|---|---|
"w" | Escrita (texto) | Trunca (apaga) o arquivo | Cria um novo arquivo |
"a" | Append (texto) | Move o ponteiro para o final | Cria um novo arquivo |
"x" | Criação exclusiva | Lança FileExistsError | Cria um novo arquivo |
"wb" | Escrita (binária) | Trunca o arquivo | Cria um novo arquivo |
"ab" | Append (binário) | Move o ponteiro para o final | Cria um novo arquivo |
"r+" | Leitura + escrita | Abre no lugar | Lança FileNotFoundError |
A coisa mais importante a lembrar sobre o modo "w": ele apaga silenciosamente o arquivo inteiro antes de escrever. Se você quiser apenas adicionar conteúdo a um arquivo existente, use o modo "a" (append) em vez disso.
Sempre forneça o parâmetro encoding ao escrever arquivos de texto para que seu código se comporte de forma idêntica no Windows, macOS e Linux:
file = open("output.txt", "w", encoding="utf-8")Sempre Use um Bloco with
Chamar open() sem um bloco with significa que você deve chamar file.close() por conta própria. Esquecer de fechar um arquivo leva a dados em buffer que nunca são gravados em disco, erros de muitos arquivos abertos em scripts de longa duração e corrupção de arquivo em alguns sistemas operacionais.
A instrução with (um gerenciador de contexto) resolve todos esses problemas. Python fecha o arquivo automaticamente quando o bloco termina — mesmo que uma exceção seja lançada dentro do bloco.
with open("output.txt", "w", encoding="utf-8") as f:
f.write("Hello, World!\n")
# File is closed and flushed here — guaranteedTodos os exemplos neste capítulo usam a instrução with. Evite o padrão manual open() / close().
Escrevendo Texto com write()
file.write(string) escreve a string fornecida no arquivo e retorna o número de caracteres escritos. Ele não adiciona uma quebra de linha automaticamente — você deve incluir \n por conta própria.
Escrever uma única linha em um novo arquivo
with open("greeting.txt", "w", encoding="utf-8") as f:
chars_written = f.write("Hello, World!\n")
print(chars_written) # 14Escrever múltiplas linhas chamando write() repetidamente
with open("poem.txt", "w", encoding="utf-8") as f:
f.write("Roses are red,\n")
f.write("Violets are blue,\n")
f.write("Python is great,\n")
f.write("And so are you.\n")Cada chamada a write() adiciona ao arquivo na posição atual. O arquivo é escrito do zero (qualquer conteúdo anterior é perdido) porque o modo "w" foi usado.
Escrevendo Múltiplas Linhas com writelines()
file.writelines(iterable) aceita qualquer iterável de strings — uma lista, um gerador ou uma tupla — e escreve cada item em sequência. Como write(), ele não adiciona quebras de linha entre os itens.
Escrever uma lista de linhas
lines = [
"First line\n",
"Second line\n",
"Third line\n",
]
with open("lines.txt", "w", encoding="utf-8") as f:
f.writelines(lines)Se os seus dados de origem ainda não contêm \n, adicione-o antes de escrever:
data = ["Alice", "Bob", "Charlie"]
with open("names.txt", "w", encoding="utf-8") as f:
f.writelines(name + "\n" for name in data)A expressão geradora name + "\n" for name in data é eficiente em termos de memória: Python produz cada string sob demanda em vez de construir a lista inteira na memória primeiro.
write() vs writelines() — Quando Usar Cada Um
write() | writelines() | |
|---|---|---|
| Entrada | Uma única string | Qualquer iterável de strings |
| Quebras de linha | Você controla cada \n | Você controla cada \n |
| Melhor para | Construir saída incrementalmente | Escrever uma sequência pré-montada de uma vez |
Criando um Arquivo que Não Deve Existir
Use o modo "x" (criação exclusiva) quando você quiser que Python crie um novo arquivo e falhe se o arquivo já existir. Isso evita a sobrescrita acidental de dados importantes.
try:
with open("config.txt", "x", encoding="utf-8") as f:
f.write("host=localhost\n")
f.write("port=8080\n")
except FileExistsError:
print("config.txt already exists — not overwriting.")Esse padrão é útil para gerar arquivos de saída únicos (logs, exportações, snapshots) onde uma colisão indica que algo deu errado.
Adicionando Conteúdo a um Arquivo Existente
Abrir um arquivo com o modo "a" move o ponteiro de escrita para o final do arquivo. O novo conteúdo é adicionado após o conteúdo existente; nada é apagado.
Adicionar uma entrada de log a um arquivo existente
import datetime
with open("app.log", "a", encoding="utf-8") as f:
timestamp = datetime.datetime.now().isoformat()
f.write(f"[{timestamp}] Server started\n")Se app.log ainda não existir, Python o cria. Se ele já existir, a nova linha é adicionada ao final. Executar o script várias vezes vai acumulando um log crescente.
Escrita vs Append — Escolhendo o Modo Certo
- Use
"w"quando quiser substituir completamente o conteúdo do arquivo (gerar um relatório novo, salvar nova configuração). - Use
"a"quando quiser adicionar ao conteúdo existente (log, acumulando resultados ao longo de múltiplas execuções).
Quebras de Linha e Finais de Linha
O modo de texto do Python ("w", "a", "r") traduz a quebra de linha universal \n para o final de linha nativo da plataforma na escrita:
- Windows:
\n→\r\n(CRLF) - macOS / Linux:
\npermanece\n(LF)
Esse geralmente é o comportamento correto — arquivos escritos no Windows abrem corretamente no Notepad.
Se você precisar forçar um final de linha específico independentemente da plataforma — por exemplo, ao gerar arquivos que devem ser lidos por um sistema específico — passe o parâmetro newline:
# Force Unix-style LF on all platforms (e.g. for Linux-target files)
with open("unix_file.txt", "w", encoding="utf-8", newline="\n") as f:
f.write("line one\n")
f.write("line two\n")
# Preserve line endings exactly as given (no translation at all)
with open("raw.txt", "w", encoding="utf-8", newline="") as f:
f.write("line one\r\n")
f.write("line two\n")Codificação de Caracteres
Sempre especifique encoding= ao escrever arquivos de texto. Depender do padrão da plataforma arriscas criar arquivos que não podem ser lidos em outros sistemas.
Codificações recomendadas para cenários comuns:
| Codificação | Usar quando |
|---|---|
"utf-8" | Uso geral; funciona para todos os idiomas; padrão para a maioria dos projetos Python |
"utf-8-sig" | UTF-8 com BOM — útil para arquivos que serão abertos no Excel no Windows |
"latin-1" | Arquivos legados do Oeste Europeu |
"cp1252" | Texto ANSI do Windows |
Escrever um arquivo com codificação UTF-8
with open("international.txt", "w", encoding="utf-8") as f:
f.write("English: Hello\n")
f.write("Japanese: こんにちは\n")
f.write("Arabic: مرحبا\n")Escrevendo Arquivos Binários
Abra um arquivo com o modo "wb" (escrita binária) para escrever bytes brutos em vez de strings. O modo binário é necessário para imagens, áudio, arquivos comprimidos, executáveis e quaisquer dados não textuais. Não especifique encoding no modo binário.
Escrever bytes em um arquivo binário
data = bytes([0x89, 0x50, 0x4E, 0x47]) # PNG magic bytes
with open("header.bin", "wb") as f:
f.write(data)
print(f.write(b"\r\n\x1a\n")) # 4Copiar um arquivo binário
with open("photo.jpg", "rb") as src:
content = src.read()
with open("photo_backup.jpg", "wb") as dst:
dst.write(content)Para arquivos binários grandes, leia e escreva em partes para evitar carregar o arquivo inteiro na memória:
CHUNK = 65536 # 64 KB
with open("large.bin", "rb") as src, open("large_copy.bin", "wb") as dst:
while True:
chunk = src.read(CHUNK)
if not chunk:
break
dst.write(chunk)Tratando Erros ao Escrever
Um script de qualidade de produção sempre antecipa as formas pelas quais uma escrita em arquivo pode falhar.
Tratar erros comuns de escrita
try:
with open("/etc/protected.txt", "w", encoding="utf-8") as f:
f.write("data\n")
except PermissionError:
print("Error: you do not have write permission for this file.")
except FileNotFoundError:
print("Error: one or more directories in the path do not exist.")
except IsADirectoryError:
print("Error: the path points to a directory, not a file.")
except OSError as e:
print(f"OS error: {e}")Exceções comuns que você encontrará:
| Exceção | Quando ocorre |
|---|---|
PermissionError | O processo não tem permissão de escrita |
FileNotFoundError | Um diretório intermediário no caminho não existe |
FileExistsError | Modo "x" e o arquivo já existe |
IsADirectoryError | O caminho aponta para um diretório |
OSError | Disco cheio, erro de sistema de arquivos de rede e outros problemas em nível de SO |
Veja Python Try Except para um guia completo sobre tratamento de exceções.
Escrevendo Arquivos com Segurança (Padrão de Escrita Atômica)
Um simples open("file.txt", "w") não é seguro para dados críticos: se seu script travar ou for interrompido no meio da escrita, o arquivo fica em um estado parcialmente escrito e corrompido. A solução padrão é uma escrita atômica: escrever em um arquivo temporário primeiro, depois renomeá-lo sobre o destino.
import os
import tempfile
def write_file_safely(path, content, encoding="utf-8"):
"""Write content to path atomically using a temp file + rename."""
dir_name = os.path.dirname(os.path.abspath(path)) or "."
# Write to a temp file in the same directory (same filesystem = atomic rename)
fd, tmp_path = tempfile.mkstemp(dir=dir_name)
try:
with os.fdopen(fd, "w", encoding=encoding) as f:
f.write(content)
os.replace(tmp_path, path) # atomic on POSIX; best-effort on Windows
except Exception:
os.unlink(tmp_path) # clean up if something went wrong
raise
write_file_safely("important.txt", "critical data\n")os.replace() (Python 3.3+) substitui o destino atomicamente em sistemas POSIX: leitores veem o arquivo antigo ou o novo, nunca uma escrita parcial.
Escrevendo Arquivos com pathlib
pathlib.Path (introduzido no Python 3.4) oferece uma API concisa e orientada a objetos. Para escritas simples de uma só vez, Path.write_text() e Path.write_bytes() são mais legíveis que open().
Path.write_text()
from pathlib import Path
Path("output.txt").write_text("Hello from pathlib!\n", encoding="utf-8")write_text() abre o arquivo no modo "w", escreve a string e fecha o arquivo — tudo em uma única chamada. Ele sempre sobrescreve o arquivo. Não há equivalente para append; para acrescentar use open() com o modo "a".
Path.write_bytes()
from pathlib import Path
Path("data.bin").write_bytes(b"\x00\x01\x02\x03")Construindo Caminhos com pathlib
pathlib também facilita a construção de caminhos com segurança sem concatenação de strings:
from pathlib import Path
output_dir = Path("results")
output_dir.mkdir(exist_ok=True) # create the directory if needed
report_path = output_dir / "report.txt"
report_path.write_text("Run complete.\n", encoding="utf-8")
print(report_path) # results/report.txt
print(report_path.exists()) # TrueO operador / em objetos Path une segmentos de caminho — sem necessidade de os.path.join().
Exemplo Prático: Escrevendo um Relatório CSV
O exemplo completo a seguir escreve uma lista de registros em um arquivo CSV usando apenas ferramentas embutidas (sem o módulo csv), demonstrando vários conceitos deste capítulo juntos.
from pathlib import Path
import datetime
def write_csv_report(path, headers, rows):
"""Write a simple CSV file with a header row."""
with open(path, "w", encoding="utf-8", newline="") as f:
f.write(",".join(headers) + "\n")
for row in rows:
f.write(",".join(str(v) for v in row) + "\n")
records = [
("Alice", 30, "Engineering"),
("Bob", 25, "Marketing"),
("Charlie", 35, "Finance"),
]
output = Path("staff_report.txt")
write_csv_report(output, ["Name", "Age", "Department"], records)
print(output.read_text(encoding="utf-8"))Saída esperada:
Name,Age,Department
Alice,30,Engineering
Bob,25,Marketing
Charlie,35,FinanceObserve que newline="" é passado para open() para que Python não faça dupla tradução das quebras de linha dentro das linhas CSV — isso corresponde à recomendação na documentação do módulo csv do Python.
Para qualquer coisa mais complexa (aspas, dialetos, casos extremos de Unicode) use o módulo embutido Python CSV em vez disso.
Referência Rápida
| Objetivo | Padrão de código |
|---|---|
| Criar ou sobrescrever um arquivo | open("f.txt", "w", encoding="utf-8") |
| Adicionar conteúdo a um arquivo | open("f.txt", "a", encoding="utf-8") |
| Criar somente se for novo | open("f.txt", "x", encoding="utf-8") |
| Escrever dados binários | open("f.bin", "wb") |
| Escrever uma string | f.write("text\n") |
| Escrever uma lista de strings | f.writelines(lines) |
| Escrita de texto de uma vez | Path("f.txt").write_text("...", encoding="utf-8") |
| Escrita binária de uma vez | Path("f.bin").write_bytes(b"...") |
| Escrita segura / atômica | Escrever em arquivo temporário, depois os.replace() |
Capítulos Relacionados
- Python File Handling — modos de abertura, parâmetros de
open()e a instruçãowith - Python Read Files —
read(),readline(),readlines(), iteração de linhas eseek() - Python Delete Files — excluindo arquivos e diretórios com segurança
- Python Try Except — tratamento de exceções em Python
- Python CSV — lendo e escrevendo arquivos CSV com o módulo
csv - Python JSON — serializando dados em arquivos JSON