Módulo 9 - Erros e exceções: nível avançado
Criando exceções próprias
11 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026
O que você vai aprender
- Criar uma classe de exceção herdando de Exception.
- Nomear a exceção de forma que ela conte a regra do seu programa.
- Levantar e capturar a sua própria exceção com raise e except.
- Decidir quando vale a pena criar uma exceção em vez de reusar uma embutida.
Ouvir o resumo desta aula
Um recap de cerca de 2 minutos na voz do Valim, para ouvir no trânsito ou na academia.
Ler a transcrição do resumo
Resumo da aula: Criando exceções próprias.
Os objetivos desta aula. Criar uma classe de exceção herdando de Exception. Nomear a exceção de forma que ela conte a regra do seu programa. Levantar e capturar a sua própria exceção com raise e except. Decidir quando vale a pena criar uma exceção em vez de reusar uma embutida.
Veja o essencial, parte por parte.
Por que criar a sua própria exceção. Você cria uma exceção escrevendo uma classe que herda de Exception.
Capturar a sua exceção com clareza. A grande vantagem aparece na hora de tratar.
Fixando as exceções próprias. Herde de Exception, não de BaseException, para erros normais do seu programa.
Esse foi o resumo do essencial. Para se aprofundar, leia a aula completa e responda os exercícios.
Por que criar a sua própria exceção
As exceções embutidas são ótimas, mas genéricas. ValueError diz que um valor é inválido, e nada mais. Só que o seu programa tem regras próprias. Uma conta bancária pode ter a regra "não sacar mais do que o saldo". Você poderia levantar um ValueError para isso, mas o nome não conta a história. Se, em vez disso, você levanta um SaldoInsuficienteError, qualquer pessoa que leia o código, ou que precise tratar esse caso, entende de imediato o que aconteceu. O nome da exceção vira documentação viva da regra de negócio.
class SaldoInsuficienteError(Exception):
"""Levantada quando um saque excede o saldo disponível."""
def sacar(saldo, valor):
if valor > saldo:
raise SaldoInsuficienteError(f"Saque de {valor} maior que o saldo de {saldo}")
return saldo - valor
print(sacar(100, 30)) # 70
print(sacar(100, 150)) # levanta SaldoInsuficienteErrorUma classe que herda de Exception já é uma exceção completa; o docstring explica quando ela é levantada.
Repare como a definição é curta. A classe SaldoInsuficienteError herda de Exception e o corpo é apenas um docstring que explica quando ela acontece. Poderia ser um simples pass. Isso basta porque a herança faz o trabalho pesado: aceitar a mensagem, guardar os argumentos, aparecer no traceback com o nome certo. Você só está dando um rótulo específico a um erro específico. Levantá-la é igual a levantar qualquer exceção: raise SaldoInsuficienteError com a mensagem.
Capturar a sua exceção com clareza
A grande vantagem aparece na hora de tratar. Com um nome próprio, quem chama a função consegue reagir de forma específica a esse caso, sem confundir com outros erros de valor. Um except SaldoInsuficienteError pega exatamente essa situação e mais nenhuma. Se você tivesse usado ValueError, um saque acima do saldo se misturaria com qualquer outro valor inválido, e você não conseguiria dar mensagens diferentes para problemas diferentes. A exceção própria separa as águas.
saldo = 100
try:
saldo = sacar(saldo, 150)
except SaldoInsuficienteError as erro:
print("Operação recusada:", erro)
else:
print("Novo saldo:", saldo)
# Saída:
# Operação recusada: Saque de 150 maior que o saldo de 100O as erro captura o objeto da exceção; imprimi-lo mostra a mensagem que você passou ao raise.
O trecho except SaldoInsuficienteError as erro guarda o objeto da exceção na variável erro. Imprimir esse objeto mostra a mensagem que você definiu no raise. É por isso que caprichar na mensagem compensa: ela chega inteira até quem trata o erro. Você também pode organizar várias exceções do seu programa criando uma classe base, por exemplo class ErroDaConta(Exception), e fazendo SaldoInsuficienteError e outras herdarem dela. Assim, um except ErroDaConta captura qualquer erro daquela família de uma vez, quando essa for a intenção.
Reusar ValueError
- Nome genérico, não conta a regra
- Mistura com outros valores inválidos
- except pega mais do que você queria
- Bom para validações simples e locais
Criar SaldoInsuficienteError
- Nome fala a linguagem do domínio
- Isola exatamente esse caso
- except trata só essa situação
- Bom quando quem chama precisa distinguir
Fixando as exceções próprias
Criar uma exceção é barato: uma classe curta que herda de Exception. O valor está no nome e na clareza que ele traz. Mas não crie por criar. Se o erro é local, simples e ninguém precisa distinguir, uma embutida como ValueError basta. A exceção própria compensa quando o problema faz parte das regras do seu programa e quem chama precisa tratá-lo de forma específica, como o saque acima do saldo. Na próxima aula você junta tudo em boas práticas, e no fim do módulo transforma esse SaldoInsuficienteError numa função de saque completa.
Teste rápido
Qual é o jeito correto de definir uma exceção própria no Python?
Perguntas frequentes
- De qual classe minha exceção deve herdar?
- De Exception, na quase totalidade dos casos. Ela é a base recomendada para erros que o seu programa levanta e trata. Evite herdar de BaseException, que é reservada para casos especiais do próprio Python, como a interrupção pelo teclado.
- Preciso escrever algum código dentro da classe?
- Não. Um corpo com apenas pass ou um docstring já cria uma exceção completa, porque a herança de Exception fornece tudo. Você só escreve mais quando quer guardar dados extras, como o valor do saque, criando um método de inicialização próprio.
- Como sei se vale a pena criar uma exceção própria?
- Pergunte se quem chama a função vai precisar distinguir esse erro dos demais. Se sim, um nome próprio ajuda a tratar o caso separadamente. Se o erro é local e simples, uma exceção embutida como ValueError costuma bastar, sem inventar classes novas.
- Por que o nome termina em Error?
- É uma convenção do Python. As exceções embutidas seguem esse padrão, como ValueError e KeyError. Terminar o nome da sua em Error deixa claro, só de bater o olho, que aquela classe é uma exceção, e não um dado ou uma função comum.
- Posso ter uma família de exceções relacionadas?
- Pode e é uma boa prática. Crie uma classe base, como ErroDaConta, e faça as específicas herdarem dela: SaldoInsuficienteError, ContaBloqueadaError. Assim, um except ErroDaConta captura qualquer erro da família, e um except mais específico trata um caso isolado.
- Exceção própria deixa o programa mais lento?
- Não de forma perceptível. Definir a classe custa quase nada, e levantar uma exceção própria tem o mesmo custo de levantar uma embutida. O ganho de clareza compensa muito qualquer custo, que na prática é irrelevante para o desempenho.
Fontes
Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.