Tratamento de Exceções com try except em Python

PythonBeginner
Pratique Agora

Introdução

Neste laboratório, você aprenderá a lidar com exceções de forma eficaz em Python usando a instrução try...except. Exploraremos como capturar exceções específicas como ValueError, lidar com múltiplos tipos de exceção e usar os blocos else e finally para maior controle sobre o fluxo do seu programa. Você também aprenderá a levantar (raise) exceções personalizadas para sinalizar condições de erro específicas no seu código. Através de exercícios práticos, você ganhará experiência na escrita de programas Python robustos e tolerantes a erros.

Este é um Lab Guiado, que fornece instruções passo a passo para ajudá-lo a aprender e praticar. Siga as instruções cuidadosamente para completar cada etapa e ganhar experiência prática. Dados históricos mostram que este é um laboratório de nível iniciante com uma taxa de conclusão de 100%. Recebeu uma taxa de avaliações positivas de 100% dos estudantes.

Tratar ValueError com try except

Nesta etapa, você aprenderá a lidar com um ValueError usando a instrução try...except. Um ValueError ocorre quando uma função recebe um argumento do tipo correto, mas com um valor inadequado. Um exemplo comum é tentar converter uma string que não é um número em um inteiro usando a função int().

Escreveremos um script Python que solicita ao usuário um número inteiro. Se a entrada não for um inteiro válido, capturaremos o ValueError e exibiremos uma mensagem amigável ao usuário.

No explorador de arquivos do WebIDE à esquerda, localize e abra o arquivo handle_value_error.py localizado no diretório ~/project. Em seguida, adicione o seguinte código a ele:

while True:
    try:
        x = int(input('Please enter an integer: '))
        print(f'You entered: {x}')
        break
    except ValueError:
        print('That was not a valid integer. Please try again.')

Salve o arquivo.

Agora, abra o terminal integrado e execute o script usando o comando python:

python ~/project/handle_value_error.py

O script solicitará que você insira um número inteiro. Primeiro, tente inserir um valor não inteiro como hello para ver o tratamento de erro em ação. Em seguida, insira um inteiro válido como 123 para ver o caminho de execução bem-sucedido.

Exemplo de saída:

Please enter an integer: hello
That was not a valid integer. Please try again.
Please enter an integer: 123
You entered: 123

Neste código:

  • O loop while True: garante que o programa continue solicitando a entrada até que um inteiro válido seja inserido.
  • O bloco try contém o código que pode levantar uma exceção, especificamente a chamada int(input(...)).
  • Se ocorrer um ValueError no bloco try, o código dentro do bloco except ValueError: é executado.
  • Se nenhuma exceção ocorrer, a instrução print() é executada e break sai do loop.

Isso demonstra como try...except ValueError permite que você lide graciosamente com entradas inválidas sem travar o programa.

Tratar Múltiplas Exceções

Um bloco de código pode potencialmente levantar diferentes tipos de exceções. Python permite que você lide com múltiplas exceções usando várias cláusulas except ou agrupando as exceções em uma única cláusula except.

Vamos escrever um script que realiza uma divisão. Esta operação pode levantar um ValueError se a entrada não for um número e um ZeroDivisionError se o divisor for zero.

No WebIDE, abra o arquivo ~/project/handle_multiple_exceptions.py e adicione o seguinte código. Esta versão usa blocos except separados para cada tipo de erro.

try:
    numerator = int(input("Enter the numerator: "))
    denominator = int(input("Enter the denominator: "))
    result = numerator / denominator
    print(f"Result: {result}")
except ValueError:
    print("Invalid input. Please enter integers only.")
except ZeroDivisionError:
    print("Error: Division by zero is not allowed.")

Salve o arquivo e execute-o a partir do terminal:

python ~/project/handle_multiple_exceptions.py

Teste o script com diferentes entradas para acionar cada exceção:

  1. Insira um valor não inteiro (ex: abc).
  2. Insira 0 para o denominador.
  3. Insira inteiros válidos para ambos.

Exemplo de saída para divisão por zero:

Enter the numerator: 10
Enter the denominator: 0
Error: Division by zero is not allowed.

Você também pode lidar com múltiplas exceções com uma única cláusula except agrupando-as em uma tupla. Isso é útil para executar a mesma ação para erros diferentes.

Agora, atualize o código em ~/project/handle_multiple_exceptions.py para usar esta abordagem agrupada:

try:
    numerator = int(input("Enter the numerator: "))
    denominator = int(input("Enter the denominator: "))
    result = numerator / denominator
    print(f"Result: {result}")
except (ValueError, ZeroDivisionError):
    print("An error occurred: Invalid input or division by zero.")

Salve o arquivo e execute-o novamente com os mesmos casos de teste para observar a nova mensagem de erro combinada.

Executar Código com a Cláusula else

A instrução try pode incluir uma cláusula else opcional. O código no bloco else é executado somente se o bloco try for concluído sem levantar nenhuma exceção. Isso é útil para separar o código que deve ser executado com sucesso do bloco principal try.

Vamos modificar nosso script de divisão para incluir um bloco else.

No WebIDE, abra o arquivo ~/project/try_except_else.py e adicione o seguinte código:

try:
    numerator = int(input("Enter the numerator: "))
    denominator = int(input("Enter the denominator: "))
    result = numerator / denominator
except (ValueError, ZeroDivisionError):
    print("An error occurred: Invalid input or division by zero.")
else:
    print("Division successful!")
    print(f"Result: {result}")

Salve o arquivo e execute-o a partir do terminal:

python ~/project/try_except_else.py

Teste o script com entradas que falham e com entradas bem-sucedidas:

  1. Insira 0 para o denominador para acionar uma exceção.
  2. Insira inteiros válidos e não nulos para executar o bloco else.

Exemplos de saída:

Enter the numerator: 10
Enter the denominator: 0
An error occurred: Invalid input or division by zero.
Enter the numerator: 10
Enter the denominator: 2
Division successful!
Result: 5.0

Como você pode ver, as mensagens no bloco else são impressas somente quando a divisão é bem-sucedida. Se ocorrer uma exceção, o bloco except é executado e o bloco else é ignorado.

Garantir a Execução do Código com a Cláusula finally

A instrução try também possui uma cláusula finally opcional. O código dentro do bloco finally é executado sempre, independentemente de uma exceção ter ocorrido no bloco try ou não. Isso o torna ideal para ações de limpeza, como fechar arquivos ou liberar recursos, que devem ocorrer em todos os cenários.

Vamos adicionar um bloco finally ao nosso exemplo de divisão.

No WebIDE, abra o arquivo ~/project/try_except_finally.py e adicione o seguinte código:

try:
    numerator = int(input("Enter the numerator: "))
    denominator = int(input("Enter the denominator: "))
    result = numerator / denominator
    print(f"Result: {result}")
except (ValueError, ZeroDivisionError):
    print("An error occurred: Invalid input or division by zero.")
finally:
    print("Execution finished.")

Salve o arquivo e execute-o a partir do terminal:

python ~/project/try_except_finally.py

Execute o script com entradas que falham e com entradas bem-sucedidas:

  1. Insira 0 para o denominador para acionar uma exceção.
  2. Insira inteiros válidos e não nulos.

Exemplos de saída:

Enter the numerator: 10
Enter the denominator: 0
An error occurred: Invalid input or division by zero.
Execution finished.
Enter the numerator: 10
Enter the denominator: 2
Result: 5.0
Execution finished.

Note que a mensagem "Execution finished." do bloco finally é impressa em ambos os casos. É garantido que o bloco finally será executado, tornando-o um local confiável para código de limpeza essencial.

Lançar Exceções Personalizadas

Às vezes, você precisa sinalizar uma condição de erro que não é uma exceção nativa do Python. Você pode fazer isso com a instrução raise, que permite criar e disparar suas próprias exceções. Isso é útil para tornar o tratamento de erros da sua aplicação mais específico e descritivo.

Primeiro, vamos ver como usar raise para uma exceção nativa. No WebIDE, abra o arquivo ~/project/raise_exception.py e adicione o seguinte código:

def check_positive(number):
    if number <= 0:
        raise ValueError("Input must be a positive number")
    print(f"The number {number} is positive.")

try:
    check_positive(-5)
except ValueError as e:
    print(f"Caught an exception: {e}")

try:
    check_positive(10)
except ValueError as e:
    print(f"Caught an exception: {e}")

Salve o arquivo e execute-o a partir do terminal:

python ~/project/raise_exception.py

A saída será:

Caught an exception: Input must be a positive number
The number 10 is positive.

Aqui, a função check_positive levanta um ValueError se a entrada não for positiva, o que é então capturado pelo bloco except.

Agora, vamos definir e levantar uma exceção personalizada (custom exception). Exceções personalizadas são classes que herdam da classe Exception nativa.

No WebIDE, abra o arquivo ~/project/custom_exception.py e adicione o seguinte código:

class NegativeNumberError(Exception):
    """Custom exception raised for negative numbers."""
    pass

def process_positive_number(number):
    if number < 0:
        raise NegativeNumberError("Negative numbers are not allowed")
    print(f"Processing positive number: {number}")

try:
    process_positive_number(-10)
except NegativeNumberError as e:
    print(f"Caught custom exception: {e}")

try:
    process_positive_number(20)
except NegativeNumberError as e:
    print(f"Caught custom exception: {e}")

Salve o arquivo e execute-o a partir do terminal:

python ~/project/custom_exception.py

A saída será:

Caught custom exception: Negative numbers are not allowed
Processing positive number: 20

Neste exemplo, definimos nossa própria NegativeNumberError e a levantamos sob uma condição específica. O bloco try...except então captura especificamente este tipo de erro personalizado, tornando o tratamento de erros mais preciso.

Resumo

Neste laboratório, você aprendeu a implementar um tratamento de erros robusto em Python. Você começou usando um bloco try...except para capturar um ValueError específico de uma entrada do usuário. Em seguida, expandiu isso lidando com múltiplos tipos de exceção, tanto separadamente quanto em um único bloco. Você também aprendeu a usar a cláusula else para executar código somente quando nenhuma exceção ocorre e a cláusula finally para executar código de limpeza em todas as situações. Por fim, praticou a criação e o levantamento de exceções personalizadas (custom exceptions) para lidar com erros específicos da aplicação, tornando seu código mais legível e fácil de manter.