itertools.batched strict: valide lotes completos

Publicado em: 16/09/2026
Tempo de leitura: 6 minutos
Código Python processado em lotes com itertools.batched

Ao processar muitos itens, é comum dividir uma sequência em grupos menores. O Python oferece itertools.batched() para fazer isso sem criar lógica manual, e versões recentes também permitem usar o parâmetro strict. Neste guia, você vai entender como a função trabalha, quando o modo estrito ajuda e como evitar erros em tarefas de dados, arquivos, APIs e automações.

O que é itertools.batched

itertools.batched(iterable, n) recebe qualquer iterável e devolve tuplas com até n elementos. Como o resultado é produzido sob demanda, a função combina bem com arquivos grandes, geradores e pipelines que não devem carregar tudo na memória.

from itertools import batched

numeros = range(10)
for lote in batched(numeros, 3):
    print(lote)

A saída contém grupos de três elementos, exceto o último, que pode ser menor. Esse comportamento é prático quando você quer processar tudo, mesmo que o tamanho total não seja múltiplo do lote.

O que muda com strict=True

Com strict=True, o último lote também precisa conter exatamente n itens. Se faltarem elementos, a função gera ValueError. Isso transforma uma suposição silenciosa em uma validação explícita.

from itertools import batched

for lote in batched(range(9), 3, strict=True):
    print(lote)

Esse exemplo funciona porque nove é divisível por três. Se o intervalo terminasse em dez, o último lote teria um item e o erro seria disparado. O modo estrito é útil quando cada grupo representa uma estrutura fixa: coordenadas, registros pareados, blocos criptográficos, linhas de importação ou argumentos de uma operação.

Quando usar o modo padrão

Use o comportamento padrão quando um lote incompleto ainda é válido. Um envio de mensagens pode aceitar o último grupo com menos destinatários. Um script de redimensionamento de imagens pode trabalhar com cinco arquivos por vez e terminar com apenas dois. Um consumidor de API pode enviar até cem itens por requisição, sem exigir exatamente cem.

Nesses casos, rejeitar o último lote só criaria complexidade. O objetivo é limitar o tamanho máximo, não impor uma cardinalidade fixa.

Quando strict=True é melhor

O modo estrito é indicado quando o formato dos dados exige grupos completos. Imagine uma lista plana de coordenadas: latitude, longitude, altitude. Cada registro precisa ter três valores. Se um valor estiver ausente, aceitar uma tupla menor esconderia um problema de origem.

valores = [10.2, -48.1, 800, 11.0, -47.9, 820]
coordenadas = list(batched(valores, 3, strict=True))

O mesmo raciocínio vale para pares chave-valor, RGB, matrizes, lotes de treinamento com formato rígido e dados vindos de sensores.

Validação antes do processamento

Você pode verificar o tamanho antes quando a coleção oferece len(). Porém, iteradores e geradores muitas vezes não possuem tamanho conhecido. O valor de strict é justamente validar durante o consumo.

def processar_registros(origem):
    try:
        for lote in batched(origem, 4, strict=True):
            salvar(lote)
    except ValueError as erro:
        registrar_erro(str(erro))
        raise

Esse padrão evita salvar parcialmente uma estrutura inválida. Em sistemas críticos, considere também transações, arquivos temporários ou filas de compensação.

Uso com arquivos grandes

Arquivos podem ser processados linha por linha. Assim, o consumo de memória permanece baixo.

from itertools import batched

with open('dados.txt', encoding='utf-8') as arquivo:
    for linhas in batched(arquivo, 1000):
        normalizadas = [linha.strip() for linha in linhas]
        enviar(normalizadas)

Esse exemplo aceita um último lote menor. Para um formato em que cada registro ocupa exatamente quatro linhas, use strict=True. Se o arquivo terminar no meio de um registro, o erro sinaliza corrupção ou exportação incompleta.

Uso com APIs

Muitas APIs limitam quantos IDs podem ser enviados por chamada. batched() simplifica esse controle.

for ids in batched(lista_de_ids, 50):
    resposta = cliente.buscar(ids=list(ids))
    armazenar(resposta)

Convertemos a tupla em lista apenas quando a biblioteca cliente exige JSON serializável nesse formato. Não use strict=True aqui, a menos que o contrato da API realmente exija cinquenta IDs em cada chamada.

Uso em bancos de dados

Inserções em lote reduzem viagens ao banco. Ainda assim, lotes enormes podem aumentar bloqueios e consumo de memória.

for registros in batched(gerar_registros(), 500):
    cursor.executemany(sql, registros)
    conexao.commit()

Escolha o tamanho medindo o ambiente real. Para aprender mais, veja também o conteúdo sobre Python e SQLite e o guia de Python com MySQL.

Diferença para fatiamento de listas

Uma alternativa tradicional é usar índices e slices. Ela funciona bem para listas pequenas, mas depende de uma sequência indexável e normalmente já carregada na memória. batched() aceita qualquer iterável e preserva a avaliação preguiçosa.

lotes = [dados[i:i + 100] for i in range(0, len(dados), 100)]

Para geradores, streams ou leitura incremental, a solução com itertools costuma ser mais adequada. O módulo é apresentado em Introdução ao itertools.

Cuidados com geradores

Um gerador é consumido uma única vez. Depois que batched() avança, os itens anteriores não podem ser recuperados. Evite tentar contar e depois reutilizar o mesmo gerador. Se a validação falhar no último lote, os lotes anteriores já podem ter sido processados.

Quando atomicidade for importante, acumule em armazenamento temporário, valide previamente quando possível ou use transações. Em pipelines simples, apenas registrar o erro e interromper pode ser suficiente.

Tratando o ValueError

Não capture o erro apenas para ignorá-lo. O propósito do modo estrito é denunciar um lote incompleto. Registre contexto suficiente para encontrar a causa.

try:
    grupos = list(batched(valores, 3, strict=True))
except ValueError as exc:
    raise ValueError('Dados devem formar grupos de três') from exc

Uma mensagem de domínio é mais útil do que expor apenas o detalhe interno. Para boas práticas gerais, consulte Try Except no Python.

Compatibilidade de versão

Antes de usar o parâmetro, confirme a versão do Python do servidor, da aplicação e do pipeline de CI. Ambientes locais e de produção podem estar diferentes. Consulte a documentação oficial de itertools e as notas de versão do Python para verificar quando cada recurso está disponível.

Testes recomendados

Crie testes para entrada vazia, tamanho exato, tamanho menor que o lote, múltiplos lotes e último lote incompleto. Verifique também iteradores infinitos com cuidado: batched() continuará produzindo grupos enquanto houver consumo.

def test_lotes_exatos():
    assert list(batched(range(6), 3, strict=True)) == [(0, 1, 2), (3, 4, 5)]

O conteúdo sobre testes unitários em Python ajuda a estruturar esses cenários.

Boas práticas

Dê nomes que expressem o significado do lote, não apenas “chunk”. Documente por que o tamanho foi escolhido. Use constantes quando o valor fizer parte de um contrato. Aplique strict=True somente quando lote incompleto for realmente erro. Evite converter todos os lotes em lista se o objetivo é economizar memória. Monitore tempo, falhas e quantidade de itens processados.

Conclusão

itertools.batched() oferece uma forma clara e eficiente de dividir iteráveis. O modo padrão serve para limites máximos e aceita o restante. strict=True serve para formatos rígidos e impede que dados incompletos passem silenciosamente. Ao escolher entre os dois, pense no contrato do seu domínio: o último grupo menor é válido ou representa corrupção? Essa resposta define a opção correta.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Análise de dados e cálculos com math.sumprod no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    math.sumprod: produtos escalares e médias ponderadas

    Aprenda math.sumprod no Python para produtos escalares, médias ponderadas, custos e cálculos numéricos claros e eficientes.

    Ler mais

    Tempo de leitura: 5 minutos
    16/09/2026
    Análise de dados CSV com csv.QUOTE_STRINGS no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    csv.QUOTE_STRINGS: preserve tipos em arquivos CSV

    Aprenda csv.QUOTE_STRINGS no Python para cotar textos, preservar tipos e criar arquivos CSV mais previsíveis e seguros.

    Ler mais

    Tempo de leitura: 6 minutos
    15/09/2026
    Código e caminhos de arquivos para PurePath.full_match no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    PurePath.full_match: valide caminhos com glob

    Aprenda PurePath.full_match no Python para validar caminhos completos com padrões glob, controlar maiúsculas e evitar filtros imprecisos.

    Ler mais

    Tempo de leitura: 6 minutos
    15/09/2026
    Código assíncrono representando asyncio.eager_task_factory no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    asyncio.eager_task_factory: reduza overhead de tarefas

    Aprenda asyncio.eager_task_factory no Python para reduzir overhead, entender mudanças de ordem e otimizar corrotinas curtas com segurança.

    Ler mais

    Tempo de leitura: 4 minutos
    14/09/2026
    Desenvolvedor trabalhando com timestamps UTC e calendar.timegm no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    calendar.timegm: converta UTC para timestamp Unix

    Aprenda calendar.timegm no Python para converter datas UTC em timestamps Unix com segurança, testes e integração com datetime.

    Ler mais

    Tempo de leitura: 6 minutos
    14/09/2026
    Programador analisando código para identificar tipos MIME de arquivos no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    mimetypes.guess_file_type: detecte tipos MIME

    Aprenda mimetypes.guess_file_type no Python para detectar tipos MIME em caminhos, URLs, uploads e respostas HTTP com fallbacks seguros.

    Ler mais

    Tempo de leitura: 6 minutos
    13/09/2026