ExceptionGroup.split: separe exceções por tipo

Publicado em: 28/10/2026
Tempo de leitura: 5 minutos
Código Python com tratamento de grupos de exceções

ExceptionGroup.split() é um recurso do Python para separar um grupo de exceções em duas partes: as que correspondem a um critério e as que não correspondem. Ele é especialmente útil em aplicações que executam várias tarefas, processam registros em lote ou recebem resultados de diferentes serviços. Nessas situações, mais de uma operação pode falhar ao mesmo tempo, e guardar todas as falhas em um único grupo permite analisar o cenário completo sem perder detalhes importantes.

O que é ExceptionGroup

Um ExceptionGroup reúne várias exceções relacionadas sob uma mesma mensagem. Imagine um processo que valida dezenas de arquivos. Um arquivo pode não existir, outro pode ter permissão insuficiente e outro pode conter dados inválidos. Em vez de interromper tudo na primeira falha, a aplicação pode coletar os problemas e criar um grupo. Assim, cada erro continua disponível para registro, diagnóstico e tratamento.

O recurso foi criado para tornar mais natural o tratamento de falhas em tarefas paralelas e fluxos compostos. Ele também funciona bem em validações, importações, testes e integrações. O objetivo não é esconder exceções, mas organizá-las sem descartar informação.

Como split funciona

O método split() recebe um tipo de exceção, uma tupla de tipos ou uma função de filtro. O retorno é uma tupla com dois elementos. O primeiro contém as exceções que correspondem ao critério. O segundo contém o restante. Quando uma parte não possui itens, o valor retornado para ela é None.

grupo = ExceptionGroup(
    "falhas de validação",
    [ValueError("idade inválida"), TypeError("tipo incorreto")],
)

valores, outros = grupo.split(ValueError)

Nesse caso, valores contém o ValueError e outros contém o TypeError. A operação não modifica o grupo original. Ela cria novas estruturas derivadas, preservando a mensagem e a organização necessária.

Filtrando mais de um tipo

Também é possível passar uma tupla com vários tipos. Isso ajuda quando diferentes exceções pertencem à mesma categoria prática.

arquivos, restante = grupo.split(
    (FileNotFoundError, PermissionError)
)

Essa separação permite tratar falhas de arquivo de uma forma e manter erros de validação ou de programação em outra parte. O resultado fica mais claro do que uma sequência longa de testes manuais.

Usando uma função como filtro

O critério pode ser uma função que recebe a exceção e retorna verdadeiro ou falso. Essa opção é útil quando a decisão depende de atributos personalizados, códigos de resposta ou outras informações.

class ErroServico(Exception):
    def __init__(self, codigo, mensagem):
        super().__init__(mensagem)
        self.codigo = codigo


def temporario(exc):
    return isinstance(exc, ErroServico) and exc.codigo >= 500

retry, definitivos = grupo.split(temporario)

Com esse padrão, apenas as falhas temporárias podem ser enviadas para uma nova tentativa. Erros definitivos ficam separados para registro ou correção dos dados.

Exemplo em validação de registros

Considere uma função que recebe vários registros e deseja informar todos os problemas encontrados.

def validar_registros(registros):
    erros = []

    for indice, registro in enumerate(registros):
        try:
            if "email" not in registro:
                raise KeyError(f"registro {indice}: email ausente")
            if registro.get("idade", 0) < 0:
                raise ValueError(f"registro {indice}: idade inválida")
        except Exception as exc:
            erros.append(exc)

    if erros:
        raise ExceptionGroup("erros de validação", erros)

Na camada que chama essa função, os campos ausentes podem ser separados dos valores inválidos. Isso permite mostrar mensagens diferentes ao usuário e registrar cada categoria de forma apropriada.

try:
    validar_registros(registros)
except ExceptionGroup as grupo:
    ausentes, restante = grupo.split(KeyError)

    if ausentes:
        registrar_campos_ausentes(ausentes)

    if restante:
        raise restante

O ponto mais importante é não ignorar o grupo restante. Se uma parte é tratada e a outra desaparece, falhas relevantes podem ficar sem registro.

Estruturas aninhadas

Grupos podem conter outros grupos. Isso acontece quando cada etapa de um pipeline ou cada tarefa produz seu próprio conjunto de erros. O método split() preserva essa árvore. Se uma falha veio da etapa de download, essa informação continua presente depois da divisão.

grupo = ExceptionGroup(
    "pipeline",
    [
        ExceptionGroup("download", [TimeoutError("tempo esgotado")]),
        ExceptionGroup("leitura", [ValueError("conteúdo inválido")]),
    ],
)

Ao separar TimeoutError, o resultado mantém o subgrupo chamado download. Isso facilita identificar a origem do problema.

split e subgroup

O método subgroup() retorna apenas a parte que corresponde ao filtro. Já split() retorna duas partes: correspondências e restante. Use subgroup() quando você só precisa consultar um subconjunto. Use split() quando precisa tratar uma categoria e depois continuar trabalhando com as outras exceções.

Boas práticas

Prefira filtrar por tipos ou atributos estáveis. Mensagens de erro podem mudar, ser traduzidas ou incluir detalhes variáveis. Evite depender apenas do texto. Também mantenha os grupos pequenos e relacionados ao mesmo contexto. Um grupo muito amplo, com erros de áreas diferentes, dificulta a leitura.

Registre o grupo completo antes de aplicar tratamentos destrutivos. Em sistemas importantes, inclua identificadores da tarefa, do arquivo ou do registro. Isso ajuda a reproduzir a falha. Nunca use split() apenas para descartar erros silenciosamente.

Testes

Os testes devem verificar os dois retornos, os tipos presentes e a preservação da estrutura.

def test_split_por_tipo():
    grupo = ExceptionGroup(
        "teste",
        [ValueError("a"), TypeError("b")],
    )

    valores, outros = grupo.split(ValueError)

    assert valores is not None
    assert outros is not None
    assert isinstance(valores.exceptions[0], ValueError)
    assert isinstance(outros.exceptions[0], TypeError)

Também teste casos sem correspondência e casos em que todas as exceções correspondem. Isso confirma o comportamento de None nos retornos.

Quando usar

O método é adequado para processamento em lote, tarefas concorrentes, pipelines de dados, chamadas a vários serviços, validações de formulários, importações e testes compostos. Em funções simples que só produzem uma falha por vez, o tratamento tradicional costuma ser suficiente.

Conclusão

ExceptionGroup.split() ajuda a organizar múltiplas falhas sem perder contexto. Ele separa erros por tipo ou condição, preserva grupos aninhados e permite tratar apenas aquilo que a aplicação conhece. O restante pode continuar sendo propagado com segurança. Para complementar o estudo, veja os artigos da Academify sobre try e except, traceback, asyncio e erros comuns. Consulte ainda a documentação oficial e a PEP 654.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Código Python com anotações de tipos em uma tela
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    evaluate_forward_ref: resolva referências futuras

    Aprenda typing.evaluate_forward_ref para resolver referências futuras com namespaces corretos, segurança, cache e testes.

    Ler mais

    Tempo de leitura: 7 minutos
    28/10/2026
    Código Python e variáveis de ambiente
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    os.reload_environ: atualize variáveis de ambiente

    Aprenda a atualizar os.environ com os.reload_environ, entenda riscos de concorrência, limites e padrões seguros para configurações dinâmicas.

    Ler mais

    Tempo de leitura: 6 minutos
    27/10/2026
    Código Python com sincronização por RLock
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    RLock.locked: detecte locks reentrantes

    Aprenda RLock.locked no Python para diagnosticar bloqueios reentrantes, testar liberações e evitar condições de corrida.

    Ler mais

    Tempo de leitura: 5 minutos
    27/10/2026
    Código Python exibindo avisos e diagnóstico para desenvolvedores
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    skip_file_prefixes: warnings no código correto

    Aprenda a usar skip_file_prefixes no módulo warnings para apontar avisos ao código correto em bibliotecas Python.

    Ler mais

    Tempo de leitura: 5 minutos
    26/10/2026
    Pasta de arquivos protegidos representando extração TAR segura no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    Extração TAR segura com tarfile no Python

    Aprenda a extrair arquivos TAR com segurança no Python usando filtros, limites e validação contra path traversal.

    Ler mais

    Tempo de leitura: 4 minutos
    26/10/2026
    Dois monitores executando código em paralelo
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    concurrent.interpreters: paralelismo com isolamento

    Aprenda concurrent.interpreters no Python para executar tarefas isoladas, comparar com threads e processos e explorar paralelismo real.

    Ler mais

    Tempo de leitura: 7 minutos
    25/10/2026