0%
Tratamento de exceções em Python

Exceções

Antecipe e trate os erros em seus programas

10-15 min

Tratamento de exceções em Python

As exceções são eventos que ocorrem durante a execução de um programa e que perturbam o fluxo normal de instruções. Em Python, as exceções são objetos que representam erros. O tratamento de exceções é crucial para desenvolver aplicações robustas, capazes de lidar com situações imprevistas sem travar.

Neste tutorial, vamos explorar como identificar, tratar e criar exceções em Python.

Por que tratar exceções?

O tratamento de exceções é importante por vários motivos:

  1. Robustez: Um programa que trata corretamente as exceções pode continuar funcionando mesmo quando ocorrem erros.
  2. Experiência do usuário: Exibir mensagens de erro amigáveis em vez de rastreamentos de erro técnicos.
  3. Depuração: Obter informações detalhadas sobre o erro para facilitar a correção.
  4. Gerenciamento de recursos: Garantir que os recursos (arquivos, conexões de rede etc.) sejam corretamente liberados, mesmo em caso de erro.

Tipos de exceções comuns em Python

O Python inclui muitos tipos de exceções embutidos. Veja alguns dos mais comuns:

  • SyntaxError: Erro na sintaxe do código.
  • NameError: Tentativa de usar uma variável não definida.
  • TypeError: Operação ou função aplicada a um objeto de tipo inadequado.
  • ValueError: Operação ou função recebe um argumento do tipo correto, mas com um valor inadequado.
  • IndexError: Tentativa de acessar um índice que não existe em uma sequência.
  • KeyError: Tentativa de acessar uma chave que não existe em um dicionário.
  • FileNotFoundError: Tentativa de abrir um arquivo que não existe.
  • ZeroDivisionError: Divisão por zero.
  • ImportError: Falha ao importar um módulo.
  • IOError: Erro de entrada/saída (por exemplo, ao ler um arquivo).
  • AttributeError: Tentativa de acessar um atributo inexistente.

Estrutura try-except-else-finally

O Python usa os blocos try, except, else e finally para tratar exceções.

Estrutura básica try-except

try:
    # Código suscetível de gerar uma exceção
    resultat = 10 / 0
except ZeroDivisionError:
    # Código executado se ocorrer uma ZeroDivisionError
    print("Erreur : Division par zéro !")

Neste exemplo, quando 10 / 0 gera uma ZeroDivisionError, o bloco except correspondente é executado.

Capturar vários tipos de exceções

Você pode capturar diferentes tipos de exceções com tratadores distintos:

try:
    # Código suscetível de gerar exceções
    nombre = int(input("Entrez un nombre : "))
    resultat = 10 / nombre
except ValueError:
    # Executado se a entrada não for um número válido
    print("Erreur : Veuillez entrer un nombre valide.")
except ZeroDivisionError:
    # Executado se nombre == 0
    print("Erreur : La division par zéro n'est pas autorisée.")

Você também pode capturar várias exceções com o mesmo tratador:

try:
    # Código suscetível de gerar exceções
    nombre = int(input("Entrez un nombre : "))
    resultat = 10 / nombre
except (ValueError, ZeroDivisionError):
    # Executado se uma das exceções mencionadas ocorrer
    print("Erreur : Entrée invalide ou division par zéro.")

Capturar todas as exceções

Embora geralmente não seja recomendado (pois pode mascarar erros inesperados), você pode capturar todas as exceções:

try:
    # Código suscetível de gerar qualquer exceção
    # ...
except Exception as e:
    # Executado para qualquer exceção que herde de Exception
    print(f"Une erreur s'est produite : {e}")

Bloco else

O bloco else é executado se nenhuma exceção for levantada no bloco try:

try:
    nombre = int(input("Entrez un nombre : "))
    resultat = 10 / nombre
except ValueError:
    print("Entrée invalide.")
except ZeroDivisionError:
    print("Division par zéro.")
else:
    # Este bloco é executado se nenhuma exceção for levantada
    print(f"Le résultat est {resultat}")

Bloco finally

O bloco finally é executado aconteça o que acontecer, seja ou não levantada uma exceção:

try:
    fichier = open("donnees.txt", "r")
    # Operações sobre o arquivo
except FileNotFoundError:
    print("Le fichier n'existe pas.")
finally:
    # Este bloco é sempre executado
    # Ideal para liberar recursos
    if 'fichier' in locals():
        fichier.close()
        print("Fichier fermé.")

O bloco finally é particularmente útil para garantir que os recursos sejam corretamente liberados, mesmo em caso de erro.

Levantar exceções

Você pode levantar (ou “throw”) exceções deliberadamente usando a instrução raise:

def diviser(a, b):
    if b == 0:
        raise ZeroDivisionError("Division par zéro non autorisée")
    return a / b

try:
    resultat = diviser(10, 0)
except ZeroDivisionError as e:
    print(f"Erreur : {e}")

Criar exceções personalizadas

Você pode criar seus próprios tipos de exceções herdando da classe Exception ou de uma de suas subclasses:

class ValeurNegativeError(Exception):
    """Exceção levantada quando um valor negativo é usado sem que deveria ser."""
    pass

def calculer_racine_carree(nombre):
    if nombre < 0:
        raise ValeurNegativeError("La racine carrée d'un nombre négatif n'est pas définie pour les nombres réels.")
    import math
    return math.sqrt(nombre)

try:
    resultat = calculer_racine_carree(-1)
except ValeurNegativeError as e:
    print(f"Erreur : {e}")

Asserções

As asserções (assertions) são verificações de depuração que testam se uma condição é verdadeira. Se a condição for falsa, uma exceção AssertionError é levantada:

def diviser(a, b):
    assert b != 0, "Le diviseur ne peut pas être zéro"
    return a / b

try:
    resultat = diviser(10, 0)
except AssertionError as e:
    print(f"Assertion échouée : {e}")

As asserções são usadas principalmente para depuração e testes, e podem ser desativadas em modo de produção.

Com a instrução with

A instrução with é usada para garantir que os recursos sejam corretamente gerenciados, mesmo em caso de exceção. É uma maneira mais limpa de tratar exceções em operações que exigem recursos como arquivos:

try:
    with open("fichier.txt", "r") as fichier:
        contenu = fichier.read()
        # O arquivo é automaticamente fechado ao fim do bloco with,
        # mesmo se uma exceção for levantada
except FileNotFoundError:
    print("Le fichier n'existe pas.")

Hierarquia das exceções

As exceções em Python formam uma hierarquia. Veja uma parte simplificada dessa hierarquia:

  • BaseException
    • Exception
      • ArithmeticError
        • ZeroDivisionError
        • OverflowError
      • LookupError
        • IndexError
        • KeyError
      • OSError
        • FileNotFoundError
        • PermissionError
      • TypeError
      • ValueError
      • …
    • SystemExit
    • KeyboardInterrupt
    • …

Ao capturar exceções, a ordem é importante. Se você tiver vários blocos except, o Python os verifica em ordem. Se uma exceção for subclasse de outra exceção que você já capturou, ela nunca será alcançada:

try:
    # Código suscetível de gerar exceções
    # ...
except Exception:
    # Este bloco capturará todas as exceções que herdam de Exception
    print("Une exception s'est produite")
except ZeroDivisionError:
    # Este bloco NUNCA será alcançado, pois ZeroDivisionError é uma subclasse de Exception
    print("Division par zéro")

Para evitar esse problema, coloque as exceções mais específicas antes das mais gerais.

Boas práticas no tratamento de exceções

  1. Seja específico: Capture exceções específicas em vez de usar um except genérico.

  2. Não suprima erros silenciosamente: Evite capturar uma exceção sem tratá-la corretamente ou sem deixar um registro.

  3. Use finally para a limpeza: Use o bloco finally para garantir que os recursos sejam corretamente liberados.

  4. Crie exceções personalizadas quando apropriado: Isso pode tornar seu código mais legível e permitir um tratamento de erros mais refinado.

  5. Mantenha os blocos try pequenos: Coloque no bloco try apenas o código suscetível de gerar a exceção.

  6. Registre as exceções em log: Em aplicações de produção, considere gravar as exceções em arquivos de log.

Conclusão

O tratamento eficaz de exceções é uma habilidade essencial para qualquer programador Python. Ele permite escrever programas robustos, capazes de lidar com erros de maneira elegante.

Neste tutorial, exploramos como identificar, capturar e levantar exceções, como criar seus próprios tipos de exceções e como usar a instrução with para gerenciar recursos. Também discutimos as boas práticas para um tratamento eficaz de exceções.

No próximo tutorial, abordaremos a manipulação de arquivos em Python, uma área em que o tratamento de exceções é particularmente importante.

Comentários

Os comentários são alimentados pelo GitHub Discussions

Conecte-se com o GitHub para participar da discussão

Link copiado!