bytearray.resize: redimensione buffers com segurança

Publicado em: 24/10/2026
Tempo de leitura: 5 minutos
Código binário representando bytearray.resize no Python

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] = 1

Essa 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 pacote

Combine 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.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Código Python em notebook para filtrar valores None
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    operator.is_none: filtre None sem perder falsy

    Aprenda operator.is_none e is_not_none para filtrar None sem remover valores falsy válidos no Python.

    Ler mais

    Tempo de leitura: 4 minutos
    23/10/2026
    Código Python em um notebook para criar dataclasses dinâmicas
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    make_dataclass decorator: transforme dataclasses

    Aprenda a usar o parâmetro decorator de make_dataclass para validar, registrar e transformar dataclasses dinâmicas no Python.

    Ler mais

    Tempo de leitura: 6 minutos
    23/10/2026
    Estrutura de código e XML para canonicalização com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    ElementTree canonicalize: normalize XML no Python

    Aprenda ElementTree canonicalize no Python para comparar XML, gerar hashes estáveis e controlar namespaces, espaços e comentários.

    Ler mais

    Tempo de leitura: 5 minutos
    22/10/2026
    Código de programação Python em uma tela
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    T-strings e templatelib: interpolação estruturada

    Aprenda t-strings e string.templatelib no Python para processar interpolações, criar renderizadores seguros e preservar dados estruturados.

    Ler mais

    Tempo de leitura: 6 minutos
    22/10/2026
    Banco SQLite e código Python para exportação seletiva com iterdump
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    SQLite iterdump: crie dumps seletivos no Python

    Aprenda sqlite3.Connection.iterdump com filtro para gerar dumps seletivos, validar dependências e restaurar bancos com segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    21/10/2026
    Código e arquivos representando compressão de dados no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    compression.zstd: Zstandard rápido no Python

    Aprenda a usar compression.zstd no Python para comprimir e descomprimir dados com desempenho, streaming e segurança.

    Ler mais

    Tempo de leitura: 7 minutos
    21/10/2026