O método bytearray.resize() permite alterar diretamente o tamanho de um buffer mutável no Python. Ele é útil quando uma aplicação precisa reservar espaço, reduzir dados já processados ou adaptar um bloco binário sem criar manualmente um novo bytearray. Embora a operação pareça simples, ela exige atenção a referências de memória, preenchimento com zeros, protocolos binários, validação de limites e compatibilidade entre versões.
O que é um bytearray
bytearray representa uma sequência mutável de bytes. Diferente de bytes, que é imutável, ele aceita alterações por índice, fatias e diversos métodos. Isso o torna adequado para montagem de pacotes, leitura incremental, buffers de rede, arquivos binários e integração com APIs que trabalham com memória. Para revisar conceitos relacionados, consulte os guias sobre tipos de dados em Python, leitura de arquivos grandes, arquivos no Python e módulo os.
Como resize funciona
Ao receber um tamanho maior, resize() expande o objeto e preenche a nova área com bytes zero. Ao receber um tamanho menor, remove os bytes excedentes no final. A alteração ocorre no próprio objeto, portanto variáveis que apontam para o mesmo bytearray observam o novo tamanho.
dados = bytearray(b"ABC")
dados.resize(6)
print(dados) # bytearray(b'ABC\x00\x00\x00')
dados.resize(2)
print(dados) # bytearray(b'AB')O método não retorna um novo buffer. Seu retorno é None, seguindo o padrão de operações mutáveis do Python.
Expansão e preenchimento com zero
O preenchimento automático com zero é conveniente para reservar espaço, mas não significa que os novos bytes já contenham informação válida. Em um protocolo, arquivo ou estrutura binária, zero pode ter significado específico. Antes de transmitir ou persistir o buffer, escreva explicitamente todos os campos esperados.
cabecalho = bytearray(b"PKT")
cabecalho.resize(8)
cabecalho[3:7] = (1250).to_bytes(4, "big")
cabecalho[7] = 1Essa abordagem evita concatenações sucessivas e deixa claro qual tamanho final é esperado.
Redução do buffer
Reduzir um bytearray descarta definitivamente os bytes localizados após o novo limite. Antes da redução, valide se eles já foram processados ou armazenados. Em parsers incrementais, uma estratégia comum é consumir uma mensagem e manter apenas os bytes restantes.
buffer = bytearray(b"MSG1RESTO")
consumidos = 4
del buffer[:consumidos]
buffer.resize(len(buffer))Nesse exemplo, o resize() final é desnecessário porque del já alterou o comprimento. Isso mostra que o novo método não substitui todas as operações de fatia; ele é especialmente útil quando o tamanho alvo é conhecido.
Validação de tamanho
O tamanho deve ser um inteiro não negativo. Valores negativos geram erro. Além disso, dados externos nunca devem determinar uma expansão ilimitada. Um cabeçalho malicioso pode anunciar gigabytes e provocar consumo excessivo de memória.
MAX_BUFFER = 8 * 1024 * 1024
def redimensionar_seguro(buf: bytearray, tamanho: int) -> None:
if not isinstance(tamanho, int):
raise TypeError("tamanho deve ser inteiro")
if not 0 <= tamanho <= MAX_BUFFER:
raise ValueError("tamanho fora do limite")
buf.resize(tamanho)Definir limites é essencial em servidores, importadores e ferramentas que processam arquivos enviados por usuários.
Views de memória e referências exportadas
Um ponto crítico aparece quando existe um memoryview ativo sobre o mesmo objeto. O Python protege a integridade dessas referências e pode impedir redimensionamentos enquanto o buffer está exportado. A view poderia apontar para uma área que deixou de existir ou foi realocada.
dados = bytearray(b"abcdef")
visao = memoryview(dados)
try:
dados.resize(20)
finally:
visao.release()
dados.resize(20)Organize o ciclo de vida das views e libere-as antes de mudar o tamanho. Isso é particularmente importante em integração com bibliotecas nativas, NumPy e APIs de alto desempenho.
resize, extend e fatias
extend() adiciona conteúdo conhecido. resize() define um comprimento e preenche expansão com zeros. Atribuição por fatia altera uma região e pode também mudar o tamanho. Use extend() quando já possui os bytes, fatias quando substitui uma área específica e resize() quando o requisito principal é o comprimento final.
buf = bytearray(b"AB")
buf.extend(b"CD")
buf.resize(8)
buf[4:] = b"1234"Buffers de rede
Em clientes TCP, um buffer pode crescer até o tamanho informado no cabeçalho. Primeiro valide o comprimento, depois expanda e preencha os bytes conforme os dados chegam. Nunca confie apenas no valor recebido.
def preparar_pacote(prefixo: bytes, payload_size: int) -> bytearray:
limite = 1_000_000
if payload_size > limite:
raise ValueError("payload muito grande")
pacote = bytearray(prefixo)
pacote.resize(len(prefixo) + payload_size)
return pacoteCombine isso com timeouts, limites por conexão e tratamento de leituras incompletas.
Arquivos e estruturas fixas
O método também ajuda na criação de registros de tamanho fixo. Um campo textual pode ser codificado, truncado e depois preenchido com zeros.
def campo_fixo(texto: str, tamanho: int) -> bytes:
buf = bytearray(texto.encode("utf-8"))
if len(buf) > tamanho:
del buf[tamanho:]
else:
buf.resize(tamanho)
return bytes(buf)Tenha cuidado para não cortar uma sequência UTF-8 no meio. Quando o campo representa texto, limite antes por caracteres ou valide a decodificação após o corte.
Desempenho
Redimensionar pode exigir realocação e cópia interna. Evite alternar repetidamente entre tamanhos próximos em loops intensivos. Quando possível, calcule o tamanho final antecipadamente ou aumente a capacidade em blocos. Meça com dados reais usando ferramentas como timeit.
Não presuma que resize() será sempre mais rápido que concatenação, extend() ou uma única alocação. O padrão de uso determina o resultado.
Compatibilidade
O código deve verificar a versão mínima do Python adotada pelo projeto. Em ambientes antigos, uma alternativa simples é usar atribuição por fatia para reduzir e extend(b"\x00" * quantidade) para expandir.
def resize_compativel(buf: bytearray, tamanho: int) -> None:
metodo = getattr(buf, "resize", None)
if metodo is not None:
metodo(tamanho)
elif tamanho < len(buf):
del buf[tamanho:]
else:
buf.extend(b"\x00" * (tamanho - len(buf)))Testes recomendados
Teste expansão, redução, tamanho zero, tamanho igual ao atual, rejeição de valores negativos, limite máximo, conteúdo preservado e preenchimento com zeros. Inclua também testes com memoryview ativa para garantir que o código trate corretamente buffers exportados.
def test_expansao():
b = bytearray(b"xy")
b.resize(5)
assert b == bytearray(b"xy\x00\x00\x00")
def test_reducao():
b = bytearray(b"abcdef")
b.resize(3)
assert b == bytearray(b"abc")Boas práticas
Valide tamanhos antes de alocar, documente o significado dos bytes zero, libere views ativas, evite redimensionamentos repetitivos e converta para bytes quando o resultado final precisar ser imutável. Em dados sensíveis, não trate a redução como limpeza garantida da memória física; use mecanismos próprios para segredos.
Conclusão
bytearray.resize() torna explícita uma operação comum: ajustar o comprimento de um buffer mutável. Ele simplifica reservas, registros fixos e processamento binário, mas deve ser usado com limites, testes e atenção ao ciclo de vida da memória. A documentação oficial de bytearray e o guia do protocolo de buffer são referências importantes para aprofundar o comportamento.







