HOWTO · Python
Grave bytes em um arquivo em Python
Este tutorial demonstra como gravar bytes em um arquivo binário em Python
Nesta página
Para gravar bytes em um arquivo no Python, chame open() com o modo wb e passe um objeto compatível com bytes ao método write() do arquivo. Use um bloco with para fechar o arquivo automaticamente. Para acrescentar dados ao conteúdo existente, escolha ab.
Cada exemplo cria seus arquivos em um diretório temporário. O Python remove esse diretório quando termina o bloco with do exemplo. Para manter um arquivo, substitua o caminho temporário pelo destino desejado.
Como gravar bytes em um arquivo no Python
O w em wb abre um arquivo para gravação: cria o arquivo se necessário e trunca um arquivo existente assim que o abre. O b seleciona o modo binário, no qual o Python grava bytes sem codificação de texto nem tradução de quebras de linha.
Execute este exemplo para gravar os dados e lê-los de volta:
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
path = Path(directory) / "example.bin"
data = b"This is some binary data."
with open(path, "wb") as file:
written = file.write(data)
with open(path, "rb") as file:
saved = file.read()
print(written)
print(saved == data)
25
True
Para esse arquivo comum com buffer, write() retorna a quantidade de bytes gravados. O programa imprime essa quantidade e compara os dados salvos com os originais. A leitura acontece depois que o bloco de gravação fecha o arquivo e libera o buffer do Python. A extensão .bin é uma convenção de nomenclatura; o modo binário é determinado pelo argumento de modo.
Use xb se quiser criar um arquivo somente quando ele ainda não existir. Ao contrário de wb, esse modo se recusa a sobrescrever um destino existente. Nenhum dos dois modos cria diretórios-pai ausentes.
Gravar várias sequências de bytes em um arquivo
Mantenha o arquivo aberto enquanto grava blocos sucessivos. Cada chamada a write() continua na posição atual; abrir o arquivo com wb dentro do loop descartaria os blocos gravados anteriormente.
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
from pathlib import Path
from tempfile import TemporaryDirectory
chunks = [b"First line.\n", b"Second line.\n", b"Third line.\n"]
with TemporaryDirectory() as directory:
path = Path(directory) / "chunks.bin"
with open(path, "wb") as file:
for chunk in chunks:
file.write(chunk)
Cada bloco deve conter dados compatíveis com bytes, como bytes, bytearray ou uma visualização de buffer adequada. Você também pode passar um iterável de sequências de bytes para file.writelines(chunks). Apesar do nome, writelines() não adiciona separadores nem quebras de linha; inclua-os nos blocos quando necessário. Um loop também permite consumir os blocos à medida que chegam, sem juntar toda a carga útil na memória.
Gravar um bytearray em um arquivo
Um objeto bytes é imutável, enquanto um bytearray permite alterar bytes individuais ou ampliar a sequência antes de salvá-la. Ambos podem ser gravados diretamente em um arquivo binário.
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
from pathlib import Path
from tempfile import TemporaryDirectory
payload = bytearray(b"Line 1\n")
payload.extend(b"Line 2\n")
payload[0] = ord("l")
with TemporaryDirectory() as directory:
path = Path(directory) / "bytearray.bin"
with open(path, "wb") as file:
file.write(payload)
Neste exemplo, extend() adiciona outra sequência e a atribuição por índice altera o primeiro byte. Não é necessário usar bytes(payload) para gravar; faça essa conversão quando precisar de um valor imutável em outro contexto. Alterações posteriores no bytearray não atualizam o arquivo automaticamente.
Gravar dados de BytesIO em um arquivo
BytesIO, do módulo io, fornece um fluxo binário em memória. Seu método getbuffer() retorna uma visualização de todo o buffer subjacente, sem copiar o conteúdo para um objeto bytes separado.
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
from io import BytesIO
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
path = Path(directory) / "buffer.bin"
with BytesIO() as buffer:
buffer.write(b"Header\n")
buffer.write(b"Payload\n")
with buffer.getbuffer() as view:
with open(path, "wb") as file:
file.write(view)
A visualização abrange todos os dados armazenados no buffer, independentemente da posição atual do fluxo. Enquanto ela existir, o objeto BytesIO não poderá ser redimensionado nem fechado; os gerenciadores de contexto aninhados a liberam antes de fechar o fluxo. Use buffer.getvalue() quando quiser obter um valor bytes. Para copiar com buffer.read(), chame primeiro buffer.seek(0) se precisar começar do início.
Acrescentar bytes ou gravar em uma posição específica
Abra o arquivo com ab para acrescentar bytes ao final sem truncar o conteúdo existente. Esse modo também cria o destino se ele ainda não existir. Para sobrescrever bytes em um deslocamento específico de um arquivo existente, use r+b e o método seek() do objeto de arquivo.
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
path = Path(directory) / "records.bin"
with open(path, "wb") as file:
file.write(b"ABCDEF")
with open(path, "ab") as file:
file.write(b"GH")
with open(path, "r+b") as file:
file.seek(2)
file.write(b"xy")
seek(2) move a posição para o deslocamento de byte 2, contado a partir do início. A gravação seguinte substitui dois bytes, sem inserir dados nem remover o restante do conteúdo. Use truncate() explicitamente se precisar remover bytes finais após uma substituição mais curta.
r+b exige que o arquivo já exista e preserva seu conteúdo ao abri-lo. w+b permite ler e gravar, mas primeiro trunca o arquivo. Evite o modo de acréscimo para atualizações em posições específicas: as gravações são direcionadas ao final, e usar seek não é uma forma portátil de alterar esse comportamento. Apenas mover a posição para além do fim não amplia o arquivo; uma gravação posterior pode ampliá-lo, e os detalhes do espaço entre os dados dependem do sistema de arquivos.
Bufferização e gravações grandes
Arquivos binários comuns abertos com open() usam buffer por padrão. Uma configuração explícita, como buffering=8192, solicita um tamanho de buffer; ela não garante gravações mais rápidas nem obriga cada operação de gravação do sistema operacional a conter exatamente 8192 bytes.
Para dados grandes gerados pelo programa, grave blocos reutilizáveis em vez de construir um único objeto combinado:
O código e os rótulos ou saídas exibidos nesta seção permanecem em inglês.
from pathlib import Path
from tempfile import TemporaryDirectory
chunk = b"record\n" * 1024
with TemporaryDirectory() as directory:
path = Path(directory) / "large.bin"
with open(path, "wb", buffering=8192) as file:
for _ in range(100):
file.write(chunk)
Este exemplo demonstra uma configuração opcional de buffer e reutiliza um único bloco. Escolha o tamanho do buffer com base em medições da sua carga de trabalho; não há um tamanho ideal para todos os casos. Fechar o arquivo libera o buffer do Python. Chamar flush() antes transfere os dados armazenados no buffer para o fluxo subjacente, mas, por si só, não garante que sejam persistidos no armazenamento físico.
Perguntas frequentes sobre a gravação de bytes
Como faço para ler os bytes de volta? Abra o arquivo com rb e chame file.read(). O valor retornado é bytes. Para um arquivo grande, leia blocos de tamanho fixo em vez de carregar tudo de uma vez.
Posso gravar texto no modo binário? Primeiro codifique o texto, por exemplo, com text.encode("utf-8") ou bytes(text, "utf-8"). Para recuperar o texto, quem fizer a leitura deve usar a codificação correspondente. Se a tarefa envolver apenas armazenar texto, pode ser mais claro abrir o arquivo em modo de texto com encoding="utf-8".
Por que write() gera um TypeError? Um fluxo binário exige dados compatíveis com bytes. Passar diretamente uma str, um inteiro ou uma lista não atende a esse requisito. Codifique o texto ou converta uma sequência de valores inteiros de byte com bytes(values); cada inteiro deve estar no intervalo de 0 a 255.
O que acontece com uma carga útil vazia? Gravar b"" não grava bytes, mas abrir um arquivo existente com wb já o trunca. Use ab para preservar os dados existentes ao acrescentar conteúdo, inclusive quando a nova carga útil estiver vazia.
Por que o destino não foi criado? Verifique se o diretório-pai existe e se o processo tem permissão para gravar nele. Um caminho relativo é resolvido a partir do diretório de trabalho atual do processo. Trate as falhas OSError pertinentes no código da aplicação e lembre-se de que a gravação ou o fechamento ainda podem falhar mesmo depois que o arquivo for aberto com sucesso.