Article image
Fernanda Araujo
Fernanda Araujo18/06/2025 09:19
Compartilhe

Paradigmas de Linguagens de Programação em Python: Python Estruturado (Part. 05)

  • #Python

O paradigma estruturado se baseia em três pilares principais: sequência, decisão e repetição. Quando escrevemos código com foco nessa abordagem, valorizamos a clareza, a lógica linear e o controle explícito do fluxo de execução.

Neste artigo, vamos explorar o tratamento de exceções e eventos, parte essencial do paradigma estruturado, especialmente quando lidamos com erros que podem interromper o programa. Você verá como capturar e manipular erros usando try, except, e outras estruturas da linguagem Python.

Para ilustrar esse processo, vamos imaginar que somos Nico Robin, a arqueóloga de One Piece, tentando decifrar os antigos Poneglyphs. Assim como um desenvolvedor precisa entender, executar e corrigir seu código, Robin precisa interpretar símbolos, prever falhas e reagir a imprevistos durante a tradução de textos milenares.

⚠️ O que são erros e exceções?

Em Python, os erros podem ser classificados em dois grandes grupos:

  • Erros de sintaxe: são detectados antes da execução do programa.
  • Exceções: são erros detectados durante a execução.

Vamos a um exemplo simples de exceção:

Python

# Exemplo - Erro em tempo de execução
inscricao = int(input("Robin encontrou uma inscrição. Quantos símbolos o bloco possui? "))
print("Significado do fragmento:", 100 / inscricao)  # Tente digitar 0

Se o usuário digitar 0, o programa lança uma exceção do tipo ZeroDivisionError. Vamos aprender a tratar esse tipo de erro.

🛡️ Bloco try e except

Para evitar que o programa quebre, usamos o bloco try/except:

python

# Exemplo - Tratamento básico com try e except
try:
  inscricao = int(input("Robin encontrou uma inscrição. Quantos símbolos o bloco possui? "))
  significado = 100 / inscricao
  print("Tradução parcial do Poneglyph:", significado)
except ZeroDivisionError:
  print("Erro: a pedra está ilegível, Robin não pode decifrar um fragmento vazio.")

Agora o programa não interrompe sua execução e trata o erro de forma controlada.

🧠 Captura de múltiplas exceções

Podemos capturar vários tipos de erro no mesmo bloco:

python

# Exemplo - Capturando múltiplas exceções
try:
  inscricao = int(input("Robin analisa uma nova pedra. Quantos símbolos foram preservados? "))
  significado = 100 / inscricao
  print("Tradução parcial:", significado)
except ZeroDivisionError:
  print("Erro: fragmento quebrado demais para interpretação.")
except ValueError:
  print("Erro: Robin só entende números, não tente enganá-la com letras do século perdido.")

Esse tipo de estrutura ajuda a manter o controle sobre diferentes cenários de erro.

🔄 Estrutura completa: try, except, else, finally

O Python também permite tratar erros com mais detalhes, usando else e finally:

python

# Exemplo - Estrutura completa
try:
  inscricao = int(input("Quantos símbolos Robin identificou no Poneglyph? "))
  significado = 100 / inscricao
except ZeroDivisionError:
  print("Erro: símbolo ausente. A leitura foi interrompida.")
except ValueError:
  print("Erro: entrada inválida. Robin precisa de um número real.")
else:
  print("Tradução bem-sucedida:", significado)
finally:
  print("Robin encerrou a leitura e registrou os dados em seu diário.")
  • else é executado se não houve exceção.
  • finally sempre é executado, ocorrendo ou não erro.

🎯 Exceções personalizadas e uso com funções

Também é possível criar exceções personalizadas para deixar o código mais claro e modular:

python

# Exemplo - Criando uma exceção personalizada
def traduzir_simbolo(simbolo):
  if simbolo.strip() == "":
      raise ValueError("Esse símbolo está em branco! Robin não consegue traduzir o vazio.")
  print(f"Símbolo '{simbolo}' traduzido com sucesso por Robin.")


try:
  simbolo_encontrado = input("Digite o símbolo encontrado por Robin: ")
  traduzir_simbolo(simbolo_encontrado)
except ValueError as erro:
  print("Erro na tradução:", erro)

Esse padrão é muito usado em aplicações reais, principalmente quando trabalhamos com validações.

🧰 Tratamento de eventos na prática

Embora Python não tenha um sistema de eventos como em linguagens voltadas a interfaces gráficas, podemos simular tratamento de eventos com funções e exceções, especialmente em sistemas com lógica baseada em ações:

python

# Exemplo - Simulando evento de descoberta arqueológica
def ao_interpretar():
  print("Robin decifrou um símbolo oculto! Iniciando anotação...")


try:
  evento = input("Digite 'ler' para simular a leitura do símbolo antigo: ")
  if evento != "ler":
      raise Exception("Evento inesperado. Robin não reconhece essa ação.")
  ao_interpretar()
except Exception as e:
  print("Erro durante a leitura:", e)

🔁 Uso de loops com tratamento de exceções

Mostra como a estrutura repetitiva (while/for) se combina com tratamento de erros para criar fluxos mais seguros:

python

# Exemplo - Validação contínua com while e try
while True:
  try:
      linhas = int(input("Quantas linhas Robin conseguiu identificar no Poneglyph? "))
      if linhas < 0:
          raise ValueError("Não é possível identificar linhas negativas.")
      break
  except ValueError as e:
      print("Erro na leitura:", e)


print("Registro arqueológico salvo com sucesso:", linhas, "linhas.")

Por que incluir? Mostra um caso de uso real com repetição e validação — muito usado em sistemas de cadastro e formulários.

🧪 Demonstração de traceback para debugging

Apresenta a biblioteca traceback que imprime o erro completo — muito útil para depuração.

python

# Exemplo - Rastreando falha na leitura do símbolo
import traceback


try:
  resultado = 1 / 0
except Exception:
  print("Erro durante a análise simbólica:")
  traceback.print_exc()

Por que incluir? Mostra ao leitor como rastrear exatamente onde o erro ocorreu — isso ensina boas práticas de depuração.

🧰 Importação de funções/módulos com try/except

Você pode ilustrar como proteger importações externas com exceções:

python

# Exemplo - Tentando acessar uma biblioteca de traduções antigas
try:
  import glyphdecoder as gd
except ImportError:
  print("Módulo 'glyphdecoder' não encontrado. Robin usará métodos manuais.")

Por que incluir? Aborda um item que você mencionou: uso de pacotes externos com segurança.

🧱 Organização em funções + exceções

Você pode mostrar como organizar tudo isso dentro de funções reutilizáveis, mantendo o código estruturado:

python

# Exemplo - Função para interpretação segura de símbolos
def interpretar_simbolo(simb1, simb2):
  try:
      return simb1 / simb2
  except ZeroDivisionError:
      return "Erro: tentativa de comparar símbolo com valor vazio."


print(interpretar_simbolo(10, 0))

Por que incluir? Conecta exceções com modularização, um conceito central do paradigma estruturado.

🚨 Tabela de exceções comuns

Você pode colocar uma tabela-resumo com os erros mais frequentes em Python, como um guia rápido:

image

Ajuda o leitor a memorizar os nomes e situações em que essas exceções acontecem.

📝 Contextualização em sistemas reais: logging e monitoramento de erros

  • Em projetos profissionais, não basta só capturar a exceção e mostrar mensagem no console. Usa-se logging para registrar erros em arquivos ou sistemas de monitoramento.
python

# Exemplo - Registrando falhas na leitura de Poneglyphs
import logging


logging.basicConfig(filename='registro_robin.log', level=logging.ERROR,
                  format='%(asctime)s - %(levelname)s - %(message)s')


try:
  simbolos = 1 / 0
except ZeroDivisionError as e:
  logging.error("Erro na leitura de fragmento do Poneglyph", exc_info=True) 
  • Explique a importância do logging para auditoria e manutenção.

🔄 Re-raising e tratamento seletivo de exceções

  • Mostrar como relançar exceções para não esconder erros importantes:
python

# Exemplo - Tratando e relançando erro na decodificação de símbolo
try:
  simbolo = int("um")  # entrada inválida proposital
except ValueError as e:
  print("Erro ao interpretar símbolo antigo:", e)
  raise  # Repassa o erro para outra camada de leitura

🛠️ Context Managers para controle de recursos

  • Use a construção with para garantir fechamento de arquivos, conexões, e mostrar como ele funciona por baixo dos panos com métodos __enter__ e __exit__, que também tratam exceções.
python

# Exemplo - Leitura segura de tradução de Poneglyph
with open('poneglyph_traducao.txt') as pergaminho:
  conteudo = pergaminho.read()
  print("Robin encontrou o seguinte conteúdo:", conteudo)
  • Explique o paralelo com o paradigma estruturado: controle rígido de abertura e fechamento de recursos.

🏗️ Custom Exception Hierarchy

  • Mostre como criar uma hierarquia de exceções para projetos maiores, facilitando o tratamento e a organização do código.
python

# Exemplo - Hierarquia de exceções para interpretação arqueológica
class ErroArqueologico(Exception):
  pass


class ErroDeSimbolo(ErroArqueologico):
  pass


class ErroDeLocalizacao(ErroArqueologico):
  pass


try:
  raise ErroDeSimbolo("Símbolos corrompidos no bloco de pedra.")
except ErroArqueologico as e:
  print("Falha durante a análise de Robin:", e)

✅ Testes automatizados para validação de tratamento de exceções

  • Explique a importância de testes unitários para garantir que o tratamento de exceções funciona. Mostre exemplo com pytest:
python

# Exemplo - Teste de falha ao tentar interpretar símbolo nulo
import pytest


def decifrar(simbolo, nivel):
  if nivel == 0:
      raise ZeroDivisionError("Tentativa de leitura sem contexto arqueológico.")
  return len(simbolo) / nivel


def test_decifrar_sem_nivel():
  with pytest.raises(ZeroDivisionError):
      decifrar("ancient-text", 0)

⚡ Performance e overhead do tratamento de exceções

O que é overhead em exceções?

Overhead significa o custo extra — tempo e recursos computacionais adicionais — que a execução de uma operação exige.

No caso das exceções em Python, lançar e capturar uma exceção não é tão barato quanto uma simples instrução condicional (como um if). Internamente, o mecanismo de exceções envolve:

  • Interrupção do fluxo normal do programa.
  • Construção do objeto de exceção.
  • Busca da estrutura de tratamento adequada (try/except).
  • Possível unwind da pilha de chamadas para encontrar o handler correto.
  • Execução do código no bloco except.

Esse processo consome mais recursos do que apenas avaliar uma condição.

Quando usar exceções é custoso?

Exceções são para situações excepcionais, ou seja, casos que não deveriam ocorrer na execução normal do programa.

Se você usa exceções como parte normal do fluxo de controle — por exemplo, para validar dados que são frequentemente inválidos — isso pode:

  • Tornar o código menos performático, porque o custo de levantar exceções se acumula.
  • Tornar o código mais difícil de entender, já que o fluxo fica mais difícil de seguir.

Exemplo comparativo: validação com if vs exceção:

Validação preventiva com if (mais eficiente)

python

# Robin verifica previamente se o símbolo é válido antes de decifrar
def decifrar(simbolo, nivel):
  if nivel == 0:
      return None  # símbolo ilegível
  return len(simbolo) / nivel

# Uso
resultado = decifrar("poneglyph-antigo", 0)
if resultado is None:
  print("Robin identificou que o símbolo não pode ser interpretado.")
else:
  print("Tradução obtida:", resultado)

Uso direto de exceção (mais custoso se acionada frequentemente)

python

# Robin tenta decifrar diretamente, sem verificar a qualidade do símbolo
def decifrar(simbolo, nivel):
  return len(simbolo) / nivel

try:
  print("Tradução:", decifrar("poneglyph-antigo", 0))
except ZeroDivisionError:
  print("Erro: Robin não pode dividir por uma base de tradução nula.")

Recomendações práticas

  • Use validações condicionais (if) para casos comuns ou esperados (ex: checar se lista está vazia, se divisor é zero, etc).
  • Use exceções para casos inesperados ou erros que não deveriam acontecer na lógica normal (ex: falha de conexão, arquivo inexistente, etc).
  • Em código crítico de performance, evite usar exceções em loops ou chamadas muito frequentes.
  • Para debugar e lidar com erros que realmente interrompem o programa, use exceções com logging e monitoração.

Quando você programa para sistemas grandes, como servidores web, sistemas financeiros ou jogos, otimizar o fluxo de controle faz diferença no tempo de resposta e no uso de recursos.

Usar exceções corretamente evita gargalos e mantém seu código com:

  • Clareza (fluxo fácil de entender)
  • Robustez (tratamento eficaz de erros)
  • Performance (evita custos desnecessários)

🌐 Integração com sistemas externos (exemplo com APIs REST)

  • Demonstre tratamento de exceções em chamadas a APIs com bibliotecas como requests, tratando erros de conexão, timeout, etc.
python

import requests

try:
  response = requests.get('https://api.exemplo.com/dados', timeout=5)
  response.raise_for_status()
except requests.exceptions.Timeout:
  print("Timeout na requisição")
except requests.exceptions.HTTPError as e:
  print("Erro HTTP:", e)
except requests.exceptions.RequestException as e:
  print("Erro na requisição:", e)

🔚 Conclusão

Neste artigo, exploramos o paradigma estruturado de programação em Python com foco no tratamento de erros e exceções. Compreendemos como lidar com eventos inesperados de forma segura e organizada, utilizando estruturas como try, except, else e finally, além de criar exceções personalizadas que tornam o código mais legível e fácil de manter.

Mais do que capturar erros, vimos que o verdadeiro valor está em prevenir falhas silenciosas, registrar problemas de forma adequada com logging, e manter o fluxo lógico do programa mesmo diante de situações adversas. Esse tipo de abordagem é fundamental em aplicações reais, especialmente quando lidamos com entrada de dados do usuário, arquivos ou integração com sistemas externos.

Para aplicar tudo que foi estudado na prática, desenvolvi um projeto completo e funcional no GitHub que implementa todos os tópicos abordados aqui, incluindo testes automatizados com pytest, logging, estrutura de diretórios e exceções customizadas.

Assim como Nico Robin decifra o passado ao interpretar cada fragmento com precisão, o desenvolvedor que adota o paradigma estruturado se torna capaz de entender, controlar e corrigir o fluxo do seu código, construindo sistemas sólidos, confiáveis e legíveis — linha por linha, como um verdadeiro arqueólogo do software.

🌐 Projeto open source disponível para estudo e colaboração

Você pode acessar, estudar e reutilizar o projeto como base para seus próprios estudos ou aplicações:

🔗 Acesse o projeto no GitHub: Tratamento Estruturado de Erros em Python

👉 No próximo artigo, vamos explorar Python Orientado a Objetos...

image

Compartilhe
Comentários (2)
DIO Community
DIO Community - 18/06/2025 15:42

Fernanda, seu artigo sobre tratamento de exceções em Python no contexto do paradigma estruturado é muito claro e didático! Você abordou de forma precisa os conceitos fundamentais, como o uso do bloco try/except, captura de múltiplas exceções e até mesmo a criação de exceções personalizadas, proporcionando uma excelente base para quem está iniciando no desenvolvimento em Python.

Você acredita que, além do tratamento de exceções, seria interessante explorar também a aplicação de padrões de design, como o Strategy Pattern, para lidar com diferentes tipos de erros em sistemas mais complexos? Como você faria isso para manter o código mais modular e organizado?

Sisnando Junior
Sisnando Junior - 18/06/2025 09:50

Excelente artigo!