
Passo 1 de 7
Reconhecer falhas que pertencem ao domínio
Identifique quais recusas de uma operação representam situações próprias da aplicação e devem ser distinguíveis por tipo.
Trilha de aprendizado · Nível 7 · Tutorial 7
Representar falhas específicas da aplicação com classes de exceção próprias e permitir que o código chamador trate cada situação no nível adequado.
Reconhecer falhas que pertencem ao domínio
Identifique quais recusas de uma operação representam situações próprias da aplicação e devem ser distinguíveis por tipo. 2 min
Definir uma exceção própria
Crie um tipo de exceção para identificar uma sessão encerrada e use a inicialização herdada para fornecer uma mensagem. 2 min
Agrupar falhas relacionadas em uma hierarquia
Organize falhas específicas de uma reserva sob uma classe base comum, preservando a identidade de cada situação. 2 min
Acrescentar contexto sem perder a mensagem
Personalize uma exceção para manter uma mensagem legível e também oferecer dados estruturados ao código chamador. 3 min
Sinalizar falhas nas operações dos objetos
Integre exceções de domínio ao método de reserva, verificando recusas antes de alterar o estado do objeto. 3 min
Tratar pelo tipo, do específico ao geral
Organize capturas específicas e gerais para responder a falhas de reserva pelo tipo, sem depender da mensagem. 3 min
Aplicar e revisar as exceções de reserva
Integre as exceções de domínio em um script Python, execute três cenários e observe como tipo, contexto e estado orientam o tratamento. 5 min

Passo 1 de 7
Identifique quais recusas de uma operação representam situações próprias da aplicação e devem ser distinguíveis por tipo.
Imagine uma operação para reservar vagas em uma sessão. Ela pode recusar o pedido porque a sessão já foi encerrada ou porque não há vagas suficientes.
Essas são falhas previstas pelas regras da aplicação. Cada uma pode merecer um tipo próprio de exceção, pois o código chamador talvez precise responder de maneira diferente a cada situação.
A mesma solicitação de reserva pode encontrar condições diferentes do domínio.

A recusa por sessão encerrada e a recusa por falta de vagas são resultados previstos e distintos da operação.
Use uma exceção de domínio quando a falha representa uma situação relevante nas regras da aplicação.
Uma restrição genérica de argumento, como receber uma quantidade negativa, ainda pode ser comunicada por uma exceção embutida adequada. Já um nome de atributo digitado incorretamente é um defeito inesperado do programa, não uma recusa prevista da reserva.
Exemplo
“Vagas insuficientes” identifica programaticamente qual falha ocorreu. Uma mensagem como “Foram solicitadas 5 vagas, mas há apenas 2 disponíveis” oferece uma explicação legível para pessoas.
O tratamento deve poder reconhecer a situação pelo tipo, sem precisar comparar ou interpretar o texto da mensagem.
Dica
Pergunte: “O chamador pode oferecer uma resposta específica para esta situação prevista?” Se sim, um tipo próprio pode tornar o comportamento da operação mais claro.
Associe cada situação à classificação mais adequada.
Toque em um item e depois no par correspondente.

Passo 2 de 7
Crie um tipo de exceção para identificar uma sessão encerrada e use a inicialização herdada para fornecer uma mensagem.
Quando uma tentativa de reserva encontra uma sessão encerrada, podemos representar essa situação com um tipo próprio. Como você já conhece herança simples, basta especializar Exception:
SessaoEncerrada identifica programaticamente a falha. Se ela não precisa guardar dados adicionais nem mudar comportamentos, seu corpo pode conter apenas pass.
Para erros usuais da aplicação, derive de Exception, não de BaseException. A classe BaseException também abrange sinais de controle como KeyboardInterrupt e SystemExit, que normalmente não devem ser tratados como falhas do domínio.
A nova classe herda de Exception tanto o comportamento de uma exceção quanto a capacidade de receber uma mensagem.

SessaoEncerrada é um tipo distinto, mas reaproveita o comportamento de Exception.
Este exemplo mínimo cria o tipo, sinaliza a falha e a captura pelo novo tipo.
class SessaoEncerrada(Exception):
pass
try:
raise SessaoEncerrada(
"Não é possível reservar: a sessão está encerrada."
)
except SessaoEncerrada as erro:
print(type(erro).__name__)
print(str(erro))Exemplo
SessaoEncerrada
Não é possível reservar: a sessão está encerrada.
Dica
A chamada SessaoEncerrada("mensagem") usa a inicialização herdada de Exception. str(erro) recupera essa mensagem, enquanto o tipo SessaoEncerrada permite reconhecer a situação sem analisar seu texto.
Complete a definição sem acrescentar um inicializador desnecessário:
class SessaoEncerrada(_):
pass
raise SessaoEncerrada("A sessão está encerrada.")

Passo 3 de 7
Organize falhas específicas de uma reserva sob uma classe base comum, preservando a identidade de cada situação.
SessaoEncerrada e VagasInsuficientes representam recusas diferentes. Ainda assim, ambas pertencem à mesma família: são falhas previstas de uma operação de reserva.
Uma classe base chamada ErroDeReserva expressa essa relação. Cada subclasse mantém sua identidade específica e, ao mesmo tempo, também pode ser reconhecida como um erro de reserva.
A hierarquia parte de Exception, passa pela família ErroDeReserva e se divide nas duas falhas específicas.

As duas classes específicas são especializações de ErroDeReserva.
A classe base deriva de Exception, pois representa uma falha usual da aplicação. As duas situações específicas passam a derivar de ErroDeReserva.
As classes precisam apenas identificar os tipos de falha neste momento, por isso podem usar o comportamento herdado.
class ErroDeReserva(Exception):
pass
class SessaoEncerrada(ErroDeReserva):
pass
class VagasInsuficientes(ErroDeReserva):
passDica
Crie uma classe quando o tipo representar uma distinção útil para o código chamador. Não é necessário criar uma subclasse para cada variação de mensagem. Nesta modelagem, a base permite reconhecer a família, enquanto as subclasses distinguem as duas causas de recusa.
Qual hierarquia permite identificar separadamente uma sessão encerrada e a falta de vagas, além de reconhecer ambas como falhas de reserva?

Passo 4 de 7
Personalize uma exceção para manter uma mensagem legível e também oferecer dados estruturados ao código chamador.
A exceção VagasInsuficientes pode servir a pessoas e ao código ao mesmo tempo. Sua mensagem explica a falha de forma legível, enquanto os atributos solicitadas e disponiveis preservam as quantidades como dados separados.
Assim, o código chamador não precisa recortar ou interpretar palavras da mensagem para descobrir os valores envolvidos.
O mesmo objeto de exceção reúne uma mensagem legível e atributos estruturados.

A mensagem é consultada com str(erro); as quantidades são consultadas diretamente nos atributos do objeto.
O __init__ recebe as quantidades, armazena cada uma em um atributo e inicializa a parte herdada com a mensagem construída.
class ErroDeReserva(Exception):
pass
class VagasInsuficientes(ErroDeReserva):
def __init__(self, solicitadas, disponiveis):
self.solicitadas = solicitadas
self.disponiveis = disponiveis
mensagem = (
f"Foram solicitadas {solicitadas} vagas, "
f"mas apenas {disponiveis} estão disponíveis."
)
super().__init__(mensagem)
erro = VagasInsuficientes(5, 2)
print(str(erro))
print(erro.solicitadas)
print(erro.disponiveis)Dica
Use str(erro) quando precisar da explicação legível. Para tomar decisões com as quantidades, use erro.solicitadas e erro.disponiveis. A redação da mensagem poderá mudar sem quebrar esse código.
Exemplo
A execução imprime:
Foram solicitadas 5 vagas, mas apenas 2 estão disponíveis.
5
2
Complete a última linha do inicializador:
class VagasInsuficientes(ErroDeReserva):
def __init__(self, solicitadas, disponiveis):
self.solicitadas = solicitadas
self.disponiveis = disponiveis
mensagem = f"Solicitadas: {solicitadas}; disponíveis: {disponiveis}."
_____Considere erro = VagasInsuficientes(5, 2). Como você obteria a mensagem legível, a quantidade solicitada e a quantidade disponível sem extrair números do texto?
Escreva pelo menos 40 caracteres (0/40).

Passo 5 de 7
Integre exceções de domínio ao método de reserva, verificando recusas antes de alterar o estado do objeto.
O método reservar deve associar cada condição prevista ao tipo correspondente: uma sessão encerrada lança SessaoEncerrada; uma quantidade maior que as vagas disponíveis lança VagasInsuficientes com as quantidades envolvidas.
As verificações acontecem antes da alteração de vagas. Assim, quando a operação é recusada, o estado da sessão permanece igual.

Somente o caminho que passa por todas as verificações chega à alteração do estado.
A docstring registra as falhas previstas como parte do comportamento público de reservar.
class ErroDeReserva(Exception):
pass
class SessaoEncerrada(ErroDeReserva):
pass
class VagasInsuficientes(ErroDeReserva):
def __init__(self, solicitadas, disponiveis):
self.solicitadas = solicitadas
self.disponiveis = disponiveis
mensagem = (
f"Foram solicitadas {solicitadas} vagas, "
f"mas apenas {disponiveis} estão disponíveis."
)
super().__init__(mensagem)
class Sessao:
def __init__(self, vagas):
self.vagas = vagas
self.encerrada = False
def encerrar(self):
self.encerrada = True
def reservar(self, quantidade):
"""Reserva vagas na sessão.
Raises:
SessaoEncerrada: se a sessão não aceita mais reservas.
VagasInsuficientes: se não há vagas para a quantidade pedida.
"""
if self.encerrada:
raise SessaoEncerrada("A sessão está encerrada.")
if quantidade > self.vagas:
raise VagasInsuficientes(quantidade, self.vagas)
self.vagas -= quantidadeDica
Com self.vagas -= quantidade depois das duas verificações, nenhum dos raise ocorre após uma alteração parcial. Se uma sessão com 3 vagas recusar uma solicitação de 5, ela continua com 3 vagas.
O objeto Sessao conhece suas regras e sinaliza por que a operação foi recusada. Ele não decide se a aplicação mostrará uma mensagem, solicitará outra quantidade ou cancelará o fluxo. Essa decisão pertence ao código chamador.
Por isso, o método lança a exceção apropriada, mas não imprime mensagens nem captura a própria falha de domínio.
Atenção
Evite envolver todo o método em except Exception para converter qualquer problema em ErroDeReserva. Um defeito inesperado, como acessar um atributo com nome incorreto, deve continuar visível como a falha original. Converta apenas situações que sejam realmente recusas previstas da operação.
Uma sessão possui 3 vagas e recebe uma solicitação de 5. Qual sequência implementa corretamente essa parte de reservar?

Passo 6 de 7
Organize capturas específicas e gerais para responder a falhas de reserva pelo tipo, sem depender da mensagem.
Um except ErroDeReserva também captura suas subclasses, como SessaoEncerrada e VagasInsuficientes. Como Python escolhe o primeiro bloco compatível, coloque a captura específica antes da captura da classe base.
Assim, o chamador pode usar os atributos de VagasInsuficientes quando essa distinção for útil e ainda oferecer uma resposta comum às demais falhas de reserva.
A busca percorre os blocos de cima para baixo e para na primeira correspondência.

VagasInsuficientes encontra primeiro sua captura específica. SessaoEncerrada passa por ela e é recebida pela captura geral de ErroDeReserva.
O primeiro bloco usa dados estruturados da exceção. O segundo trata o restante da família de forma comum.
def confirmar_reserva(sessao, quantidade):
try:
sessao.reservar(quantidade)
except VagasInsuficientes as erro:
print(
f"Não foi possível reservar {erro.solicitadas} vaga(s): "
f"há apenas {erro.disponiveis} disponível(is)."
)
except ErroDeReserva as erro:
print(f"Reserva recusada: {erro}")
else:
print("Reserva confirmada.")Atenção
Não acrescente except Exception apenas para impedir que o programa mostre uma falha. Isso também capturaria defeitos inesperados e poderia ocultar o problema. Aqui, o chamador trata somente as falhas previstas da família ErroDeReserva; outras exceções continuam se propagando.
Dica
Alterar a redação retornada por str(erro) não muda qual bloco será executado. Evite comparar mensagens: escolha o tratamento pelo tipo e consulte atributos quando precisar de detalhes.
Ordene os trechos para preservar o tratamento específico de vagas insuficientes e depois tratar as demais falhas de reserva.
Considere a ordem except VagasInsuficientes e depois except ErroDeReserva. Associe cada exceção ao resultado.
Toque em um item e depois no par correspondente.

Passo 7 de 7
Integre as exceções de domínio em um script Python, execute três cenários e observe como tipo, contexto e estado orientam o tratamento.
Crie um arquivo chamado reservas.py, copie todo o código abaixo e execute-o com python reservas.py ou python3 reservas.py. O script usa apenas Python 3 e cria uma sessão independente para cada cenário, evitando que uma tentativa interfira nas demais.
O objeto sinaliza cada recusa; o código chamador escolhe como tratar cada tipo.
class ErroDeReserva(Exception):
pass
class SessaoEncerrada(ErroDeReserva):
pass
class VagasInsuficientes(ErroDeReserva):
def __init__(self, solicitadas, disponiveis):
self.solicitadas = solicitadas
self.disponiveis = disponiveis
mensagem = (
f"Reserva de {solicitadas} vaga(s) recusada: "
f"somente {disponiveis} disponível(is)."
)
super().__init__(mensagem)
class Sessao:
def __init__(self, vagas, encerrada=False):
self.vagas = vagas
self.encerrada = encerrada
def reservar(self, quantidade):
"""Reserva vagas.
Levanta SessaoEncerrada se a sessão estiver encerrada.
Levanta VagasInsuficientes se não houver vagas suficientes.
"""
if self.encerrada:
raise SessaoEncerrada("A sessão já foi encerrada.")
if quantidade > self.vagas:
raise VagasInsuficientes(quantidade, self.vagas)
self.vagas -= quantidade
def executar_cenario(nome, sessao, quantidade):
print(f"\n--- {nome} ---")
print(f"Vagas antes: {sessao.vagas}")
try:
sessao.reservar(quantidade)
except VagasInsuficientes as erro:
print(f"Captura específica: {type(erro).__name__}")
print(f"Mensagem: {erro}")
print(f"Solicitadas: {erro.solicitadas}")
print(f"Disponíveis: {erro.disponiveis}")
except ErroDeReserva as erro:
print(f"Captura pela base: {type(erro).__name__}")
print(f"Mensagem: {erro}")
else:
print("Reserva realizada com sucesso.")
print(f"Vagas depois: {sessao.vagas}")
executar_cenario(
"Reserva bem-sucedida",
Sessao(vagas=5),
quantidade=2,
)
executar_cenario(
"Vagas insuficientes",
Sessao(vagas=2),
quantidade=4,
)
executar_cenario(
"Sessão encerrada",
Sessao(vagas=5, encerrada=True),
quantidade=1,
)Dica
VagasInsuficientes aparece antes de ErroDeReserva. Como a primeira é subclasse da segunda, inverter essa ordem faria a captura geral receber também a falta de vagas.
Na reserva bem-sucedida, duas vagas são descontadas. Nas duas recusas, a validação ocorre antes da alteração de estado: o número de vagas permanece igual. A falta de vagas aciona a captura específica e disponibiliza seus atributos; SessaoEncerrada é recebida pela captura da família ErroDeReserva.
O mesmo método pode concluir a operação ou sinalizar uma de duas falhas previstas, deixando ao chamador a escolha da resposta.

O tipo lançado determina o caminho de captura; a mensagem apenas explica a ocorrência.
Exemplo
Resultados essenciais: sucesso — vagas de 5 para 3; vagas insuficientes — tipo VagasInsuficientes, atributos solicitadas=4 e disponiveis=2, vagas de 2 para 2; sessão encerrada — tipo real SessaoEncerrada, captura por ErroDeReserva, vagas de 5 para 5.
Após executar o script, relate o que ocorreu nos três cenários. Inclua o tipo lançado, a captura acionada, os dados disponíveis e as vagas antes e depois. Explique também por que mudar apenas a mensagem das exceções não alteraria o tratamento.
Escreva pelo menos 120 caracteres (0/120).
Resumo
A solução integrada mantém separadas as responsabilidades do objeto e do chamador.
Parabéns! Você concluiu: Criar exceções para erros do domínio
100 XP
Você concluiu este nível!
Agora você vai iniciar: Testes, depuração e qualidade
Escrever e executar testes de funções com pytestCriar testes automatizados para funções, executá-los com pytest no ambiente do projeto e interpretar os resultados das verificações.Milhares de cursos online em vídeo, ebooks e áudiobooks.
Para testar seus conhecimentos no decorrer dos cursos online
Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail
Baixe nosso aplicativo pelo QR Code ou pelos links abaixo:.
+ de 10 milhões
de alunos
Certificado grátis e
válido em todo o Brasil
60 mil exercícios
gratuitos
4,8/5 classificação
nas lojas de apps
Cursos gratuitos em
vídeo, ebooks e audiobooks