🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

Dominando o Tratamento de Exceções em Python (try-except)

Para executar Python no prompt de comando ou PowerShell no seu PC, é necessário baixar e instalar o Python.
Se ainda não o fez, consulte o artigo Instalação do Python e configuração do ambiente de desenvolvimento para instalar o Python.

Ao escrever programas, é inevitável encontrar erros inesperados. As causas dos erros são variadas: entrada incorreta do usuário, ausência de um arquivo, problemas de rede, etc. Nesses momentos, o "tratamento de exceções" é o mecanismo para evitar que o programa trave subitamente e para lidar com a situação de forma inteligente.

Neste artigo, vamos explicar desde o básico até as aplicações do tratamento de exceções usando a declaração try-except do Python, com exemplos de código que você pode copiar e colar para rodar imediatamente, de uma forma fácil de entender para iniciantes. Vamos dominar como criar programas robustos e à prova de erros, experimentando o código que "funciona" na prática!


Primeiro, o básico! A sintaxe try-except

A forma mais fundamental de tratamento de exceções é a declaração try-except. Como o nome sugere, ela cria um fluxo de "try (tentar), e se uma exceção (erro) ocorrer, except (capturar e tratar)".

A sintaxe é muito simples:

  1. Dentro do bloco try, você escreve o código que tem potencial para gerar um erro.
  2. Dentro do bloco except, você escreve o código que deseja executar quando um erro ocorrer.

Ver para crer. Vamos usar o famoso "erro de divisão por zero" (ZeroDivisionError) como exemplo. No código abaixo, tentamos dividir 10 por 0. Normalmente, isso faria o programa parar com um erro, mas com o try-except, nós o capturamos de forma adequada.


<!-- Código Python -->
try:
  # Código que pode gerar um erro
  result = 10 / 0
  print(f"Resultado do cálculo: {result}")
except ZeroDivisionError:
  # Ação a ser tomada se ocorrer um ZeroDivisionError
  print("Opa! Você não pode dividir por zero.")

print("O programa foi concluído com sucesso.")
    

Mirando em exceções específicas! Múltiplos excepts

Em um programa, vários tipos de erros podem ocorrer. Por exemplo, na entrada do usuário, "era esperado um número, mas foi inserido um texto" (ValueError), ou em operações de arquivo, "o arquivo especificado não foi encontrado" (FileNotFoundError).

Ao especificar o tipo do erro (a classe da exceção) após a declaração except, você pode capturar apenas erros específicos e realizar o tratamento adequado para cada um.

Além disso, você pode alinhar múltiplos blocos except para escrever tratamentos diferentes dependendo do tipo de erro. O exemplo a seguir tenta converter uma string em um inteiro.


<!-- Código Python -->
user_input = "hello" # Um texto em vez de um número

try:
  num = int(user_input)
  print(f"Número inserido: {num}")
except ValueError:
  print("Por favor, insira um número! Um texto não pode ser convertido para número.")
except TypeError:
  print("O tipo de dado está incorreto! Não é um tipo que pode ser convertido para número.")

print("Continuando o processamento...")
    

Muitas vezes, você vai querer saber as informações detalhadas (mensagem de erro) do erro que ocorreu. Nesse caso, você pode usar as para armazenar o objeto da exceção em uma variável. Geralmente, o nome da variável e (de error ou exception) é comumente usado.


<!-- Código Python -->
try:
  # Tentativa de abrir um arquivo inexistente
  with open("arquivo_inexistente.txt", "r") as f:
    content = f.read()
except FileNotFoundError as e:
  # Exibir informações detalhadas do erro
  print(f"Arquivo não encontrado.")
  print(f"Detalhes do erro: {e}")

    

Uso avançado: Dominando else e finally

O try-except tem ainda os companheiros poderosos else e finally. Combiná-los permite um tratamento ainda mais refinado.

Vamos ver um código que usa todos esses elementos.


<!-- Código Python -->
file_path = "meus_dados.txt"
data_to_write = "Estes são dados de teste."

try:
  print(f"Escrevendo dados em '{file_path}'...")
  f = open(file_path, "w", encoding="utf-8")
  # Para causar um erro de propósito, descomente a linha abaixo
  # f.write(12345) # Tentar escrever algo que não é string causa um TypeError
  f.write(data_to_write)
  print("Tentativa de escrita concluída.")

except TypeError as e:
  print(f"Erro! Os dados a serem escritos devem ser uma string.")
  print(f"Detalhes do erro: {e}")

except Exception as e:
  # Capturar quaisquer outros erros inesperados
  print(f"Ocorreu um erro inesperado.")
  print(f"Detalhes do erro: {e}")

else:
  # Executado se nenhuma exceção ocorreu no bloco try
  print("A escrita no arquivo foi bem-sucedida!")

finally:
  # Executado sempre, com ou sem exceção
  if 'f' in locals() and not f.closed:
    f.close()
    print("O arquivo foi fechado.")
  else:
    print("O arquivo não estava aberto ou já foi fechado.")

print("--- Processamento concluído ---")
    

Na prática! Um exemplo de código completo para copiar e colar

Agora, vamos usar todo o conhecimento adquirido para criar um programa mais prático. Este código pergunta a idade ao usuário e continua pedindo repetidamente até que um número válido seja inserido. Em seguida, ele salva a idade inserida em um arquivo. Os possíveis erros que podem ocorrer no caminho são tratados com try-except.

Copie todo o código abaixo, salve-o em um arquivo chamado age_logger.py e execute-o no seu terminal com python age_logger.py. Tente inserir texto de propósito para ver como o tratamento de erros funciona!


<!-- Script Python completo: age_logger.py -->
import datetime

def record_age():
    """
    Função para perguntar a idade do usuário e registrá-la em um arquivo.
    Lida com a validação da entrada e erros de E/S (Entrada/Saída) de arquivo.
    """
    while True:
        try:
            # Receber a entrada do usuário
            age_str = input("Por favor, digite sua idade em números: ")

            # Converter a string para um inteiro
            age = int(age_str)

            # Verificar valores negativos ou idades irrealistas
            if age < 0 or age > 130:
                # Lançar um erro personalizado (raise)
                raise ValueError("A idade deve ser entre 0 e 130.")

            # Se uma idade válida for inserida, sair do loop
            break

        except ValueError as e:
            # Capturar o erro de conversão de int() ou o ValueError que lançamos
            print(f"Erro: {e}")
            print("Por favor, tente novamente com um número válido.\n")

    # Registrar no arquivo
    try:
        # A declaração "with" fecha o arquivo automaticamente, então um finally para close() não é necessário
        with open("age_log.txt", "a", encoding="utf-8") as f:
            timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            f.write(f"[{timestamp}] Idade registrada: {age} anos\n")
        
        print(f"Sua idade, '{age}' anos, foi registrada em 'age_log.txt'.")

    except IOError as e:
        # Capturar erros como falta de permissão para escrever no arquivo
        print("Erro fatal: Falha ao escrever no arquivo.")
        print(f"Detalhes do erro: {e}")

if __name__ == "__main__":
    record_age()
    print("Obrigado por usar o programa.")

    

Pontos de atenção: Capturando exceções de forma ampla

O tratamento de exceções é útil, mas se usado incorretamente, pode tornar mais difícil encontrar problemas no seu programa. Um ponto de atenção especial é capturar exceções de escopo muito amplo.

Não recomendado: except genérico

A pior prática é um except: "genérico" que não especifica uma classe de exceção. Isso captura todos os erros indiscriminadamente. Isso inclui SystemExit, que é usado para terminar o programa, e até mesmo KeyboardInterrupt ao pressionar Ctrl+C. Você pode acabar em uma situação em que nem consegue parar seu programa quando quer.

Cuidado ao usar: except Exception

except Exception as e: é melhor do que um except: genérico, mas ainda captura a maioria dos erros comuns. Durante o desenvolvimento, muitas vezes você quer que os erros ocorram para encontrar bugs inesperados. Se você capturar tudo, os bugs que deveriam ser corrigidos podem ficar ocultos.

A melhor prática é "especificar и capturar apenas as exceções que você pode prever e tratar adequadamente".


Resumo e próximos passos

Neste artigo, aprendemos sobre a declaração try-except do Python para tratamento de exceções. Vamos rever os pontos principais:

  • Você pode evitar que o programa trave por causa de erros com try-except.
  • Com except ClasseDaExcecao as e, você pode capturar erros específicos e obter informações detalhadas.
  • Use else para código de sucesso e finally para operações de limpeza.
  • O segredo é limitar a captura de exceções a casos específicos e tratáveis, em vez de ser muito amplo.

Ao dominar o tratamento de exceções, você pode construir aplicações robustas que são amigáveis para o usuário e fáceis de manter para os desenvolvedores. Não hesite em introduzir o try-except em seu próprio código!

Como próximo passo, que tal aprender sobre um conceito importante para modularizar seu programa e aumentar sua reutilização?

>> Próximo artigo: Introdução a Classes e Programação Orientada a Objetos em Python