Domine Exceções em Python: Guia Completo para Capturar Múltiplas Erros

O tratamento de exceções em Python é fundamental para assegurar que seus programas operem de forma mais estável e com menos falhas. Essa prática não apenas eleva a confiabilidade do seu código, mas também aprimora a experiência do usuário. Neste artigo, exploraremos como capturar diversas exceções dentro de um mesmo bloco try/except em Python.

O Que São Exceções em Python?

Em Python, exceções são um mecanismo de comunicação entre diferentes partes de um programa. Este mecanismo permite que uma seção do sistema informe que encontrou uma falha crítica, que não consegue resolver por si só.

Assim, é “levantada” uma exceção. Outra parte do programa, capaz de lidar com o erro, captura a exceção e a trata adequadamente.

Quando exceções não são tratadas, elas causam a interrupção do programa. O tratamento de exceções, portanto, impede que seu programa falhe e o torna mais confiável.

Para o contexto deste artigo, consideraremos que você já possui familiaridade com os conceitos básicos de gerar e tratar exceções, conforme abordado no artigo Intrudução ao Python Try/Except.

A Importância de Lidar com Múltiplas Exceções em Python

  • Reduz a repetição de código, já que múltiplas exceções podem ser tratadas pelo mesmo bloco. Isso facilita a leitura, edição e manutenção do código.
  • Auxilia na escrita de um código mais eficiente, pois o tipo de erro precisa ser verificado somente uma vez, em vez de várias vezes.

Tratamento de Múltiplas Exceções

A captura de múltiplas exceções refere-se à situação onde mais de uma exceção é interceptada utilizando o mesmo bloco `except`. Em Python, é possível capturar exceções distintas em blocos `except` separados.

Alternativamente, se o tratamento das exceções for similar, pode-se agrupar o tratamento em um único bloco. Para isso, é preciso capturar diversas exceções. Abaixo, demonstraremos como fazer isso com um exemplo.

#1. Capturando Exceções Distintas em Blocos Separados

Imagine que temos um programa projetado para receber dois números e realizar a divisão entre eles. Nesse programa, antecipamos que diferentes tipos de exceções podem surgir caso o usuário insira valores inválidos. Em particular, queremos tratar os erros `ValueError` e `ZeroDivisionError`.

O erro `ValueError` ocorre quando o usuário fornece um valor que não pode ser convertido em um número inteiro. O erro `ZeroDivisionError` é gerado quando o segundo número é zero. Em ambos os casos, queremos exibir uma mensagem de erro padronizada: “Você inseriu um valor inválido”.

Para implementar o comportamento desejado, podemos escrever o código a seguir:

try:
    dividendo = int(input('Insira o primeiro número: '))
    divisor = int(input('Insira o segundo número: '))
    quociente = dividendo / divisor
    print(quociente)
except ValueError as e:
    print("Você inseriu um valor inválido")
except ZeroDivisionError as e:
    print("Você inseriu um valor inválido")
except Exception as e:
    print("Algo deu errado")

Se executarmos o código acima e fornecermos um texto que não pode ser convertido para um número inteiro, teremos o seguinte resultado:

Se o segundo número fornecido for 0, o resultado será:

O código funciona como esperado, mas note que estamos tratando `ValueError` e `ZeroDivisionError` de forma idêntica. Há, portanto, uma repetição de código entre os dois blocos `except`. Isso não é ideal, pois violamos o princípio DRY (Don’t Repeat Yourself) da programação.

Portanto, em vez de escrever o código separadamente, podemos combinar os dois blocos em um bloco único que capture múltiplas exceções. Ao fazer isso, evitamos a repetição.

#2. Capturando Múltiplas Exceções em Um Bloco `Except`

Para capturar múltiplas exceções, fornecemos uma tupla que especifica todos os erros que queremos capturar. Abaixo está um exemplo onde capturamos `ValueError` e `ZeroDivisionError` em um único bloco `except`:

try:
    dividendo = int(input('Insira o primeiro número: '))
    divisor = int(input('Insira o segundo número: '))
    quociente = dividendo / divisor
    print(quociente)
except (ValueError, ZeroDivisionError) as e:
    print("Você inseriu um valor inválido")
except Exception as e:
    print("Algo deu errado")

Esta é uma implementação muito superior ao código anterior. Essencialmente, esta é a essência do tratamento de múltiplas exceções. O código acima funciona da mesma forma que antes. Ao testá-lo com os exemplos anteriores, ele deverá funcionar conforme o esperado:

#3. Identificando Qual Exceção Foi Capturada

O código acima executa o primeiro bloco `except` quando um `ValueError` ou `ZeroDivisionError` é capturado. Em alguns cenários, você pode ter um código que deseja executar para ambos os erros e outro código específico para apenas um deles.

Nesse caso, você deve primeiro identificar qual erro foi detectado para executar o código apropriado.

Para identificar qual exceção foi capturada, você pode usar uma estrutura condicional `if/else` dentro do bloco `except`. Por exemplo:

try:
    dividendo = int(input('Insira o primeiro número: '))
    divisor = int(input('Insira o segundo número: '))
    quociente = dividendo / divisor
    print(quociente)
except (ValueError, ZeroDivisionError) as e:
    print("Você inseriu um valor inválido")

    if isinstance(e, ValueError):
        print('Erro de Valor')
    else:
        print('Erro de Divisão por Zero')
except Exception as e:
    print("Algo deu errado")

Neste bloco, além de imprimir a mensagem de erro genérica para `ValueError` e `ZeroDivisionError`, também verificamos qual tipo de erro ocorreu e exibimos uma mensagem adicional. Se executarmos o código novamente, veremos mensagens adicionais específicas para cada exceção.

Quando Seria Adequado Tratar Múltiplas Exceções?

Em geral, lidar com múltiplas exceções é apropriado quando você deseja executar o mesmo código para exceções semelhantes que podem ser geradas. Isso inclui:

  • Requisições de rede que falham por diferentes motivos. Independente da razão, você pode notificar o usuário de que não foi possível acessar o servidor.
  • Falhas em conexões de banco de dados, que podem gerar diversos erros. Apesar de serem erros diferentes, o tratamento pode ser similar.
  • Operações de E/S de arquivo que também produzem erros que podem ser tratados de forma parecida, como erros de permissão e disco cheio.

Conclusão

Neste artigo, exploramos a combinação de vários blocos `except` em um único, capturando várias exceções de uma só vez. Essa prática torna o seu código mais legível e fácil de manter. Como próximo passo, você pode querer conferir este artigo sobre projetos para iniciantes em Python que você deve experimentar.