Módulo 12 - Exceções, logging e robustez
raise from: encadear erros sem perder a causa
9 min de leitura · por Cesar Gargiulo, revisado pela equipe ValorFinal e GuardiaSec · Atualizado em 01/07/2026
O que você vai aprender
- Traduzir um erro técnico em um erro claro do seu domínio.
- Usar raise ... from ... para preservar a causa original.
- Entender __cause__ e __context__ no rastreamento.
- Saber quando usar from None para ocultar a causa de propósito.
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: raise from: encadear erros sem perder a causa.
Os objetivos desta aula. Traduzir um erro técnico em um erro claro do seu domínio. Usar raise ... from ... para preservar a causa original. Entender __cause__ e __context__ no rastreamento. Saber quando usar from None para ocultar a causa de propósito.
Veja o essencial, parte por parte.
Traduzir erros de baixo nível. Ao capturar um erro técnico e levantar um mais claro, encadeie com raise ... from ....
__cause__ e __context__. O Python encadeia exceções de duas formas.
Quando ocultar a causa. A regra padrão é usar from para preservar a causa: informação nunca é demais ao depurar.
Esse foi o resumo do essencial. Para se aprofundar, leia a aula completa e responda os exercícios.
Traduzir erros de baixo nível
Uma prática comum e saudável é traduzir erros. Uma camada baixa do seu código pode falhar com um erro técnico, como um KeyError ao ler um dicionário ou um ValueError ao converter um texto. Repassar esse erro cru para quem chamou a sua função vaza detalhes de implementação e confunde. O melhor é capturar o erro técnico e levantar uma exceção do seu domínio, com uma mensagem clara. O cuidado é não jogar fora a causa original, que é ouro na hora de depurar.
class ConfigInvalida(Exception):
pass
def ler_porta(config):
try:
return int(config["porta"])
except KeyError as e:
raise ConfigInvalida("faltou a chave porta") from e
except ValueError as e:
raise ConfigInvalida("porta precisa ser um numero") from e
try:
ler_porta({"host": "localhost"})
except ConfigInvalida as erro:
print(erro) # faltou a chave porta
print(repr(erro.__cause__)) # KeyError('porta')raise ConfigInvalida(...) from e preserva o KeyError original em __cause__.
O from e é o que faz a mágica. A função devolve um erro limpo do domínio, ConfigInvalida, mas guarda o KeyError original em __cause__. No rastreamento completo, o Python imprime as duas exceções, com a frase A causa direta da exceção acima foi entre elas. Quem lê o log entende tanto o que deu errado do ponto de vista do domínio quanto a causa técnica exata, sem precisar adivinhar. É a diferença entre um log que ajuda e um que esconde.
__cause__ e __context__
O Python encadeia exceções de duas formas. Quando você usa raise ... from ..., ele preenche __cause__: uma ligação explícita, feita por você, dizendo que um erro foi a causa direta do outro. Mas há também o encadeamento implícito. Se uma exceção acontece dentro de um bloco except, enquanto você já tratava outra, o Python preenche __context__ automaticamente, mesmo sem from. No rastreamento, isso aparece como Durante o tratamento da exceção acima, ocorreu outra exceção.
| Situação | Atributo preenchido | Mensagem no rastreamento |
|---|---|---|
| Você usa raise ... from causa | __cause__ | A causa direta da exceção acima foi |
| Erro novo dentro de um except, sem from | __context__ | Durante o tratamento da exceção acima, ocorreu outra |
| Você usa raise ... from None | nenhum (causa oculta) | Só a nova exceção aparece |
As três formas de encadeamento e como cada uma aparece no log.
A distinção importa na prática. O __context__ implícito é útil, mas às vezes polui o rastreamento com um erro intermediário que não interessa a quem lê. Quando você usa from explicitamente, deixa claro qual é a causa que importa. E, quando quer suprimir a cadeia de propósito, existe o from None, que oculta a causa. Um caso típico é uma função pública que não quer expor detalhes internos: ela traduz o erro e usa from None para mostrar só a mensagem limpa, sem o rastro técnico.
Quando ocultar a causa
class UsuarioNaoEncontrado(Exception):
pass
_banco = {"ana": 1, "bruno": 2}
def id_do_usuario(nome):
try:
return _banco[nome]
except KeyError:
# Aqui a causa tecnica (KeyError) nao agrega nada a quem chama.
raise UsuarioNaoEncontrado(f"usuario {nome!r} nao existe") from None
try:
id_do_usuario("carla")
except UsuarioNaoEncontrado as e:
print(e) # usuario 'carla' nao existe
print(e.__cause__) # None: a causa foi ocultada de propositofrom None oculta o KeyError interno, expondo só a mensagem clara do domínio.
O bom senso aqui é claro: preservar a causa deve ser o padrão, e ocultá-la, a exceção. Um KeyError que revela a estrutura interna de um dicionário privado talvez não interesse a quem consome uma API pública, e nesse caso from None limpa o rastreamento sem perda real. Mas nunca use from None para esconder um erro que você não entendeu, porque é exatamente a causa que você precisa ver depois. Encadear bem é um dos hábitos que mais economizam tempo de depuração num sistema em produção.
Teste rápido
O que raise NovoErro(...) from erro_original faz?
Perguntas frequentes
- Se eu não usar from, perco a causa original?
- Não necessariamente. Se o novo erro é levantado dentro de um except, o Python liga as exceções por __context__ automaticamente, e o rastreamento ainda mostra as duas. O from serve para tornar essa ligação explícita e marcar qual é a causa direta que importa.
- Qual a diferença prática entre __cause__ e __context__?
- __cause__ é preenchido por você, com from, e sinaliza uma causa direta e intencional. __context__ é preenchido pelo Python quando um erro ocorre durante o tratamento de outro, sem from. Ambos aparecem no rastreamento, com frases diferentes que indicam a natureza da ligação.
- Quando devo usar from None?
- Quando a causa técnica não agrega valor a quem vai ver o erro e só poluiria o log, como esconder um detalhe interno numa API pública. Nunca use from None para ocultar um erro inesperado, porque é justamente essa causa que você vai precisar investigar depois.
- Traduzir erros não é esconder informação?
- Não, quando feito com from. Traduzir dá a quem chama uma mensagem clara do domínio, enquanto o from preserva a causa técnica no rastreamento. Você ganha clareza sem perder rastreabilidade. O que esconde informação é engolir o erro sem encadear nem registrar.
- raise from funciona com exceções embutidas?
- Sim. Você pode encadear a partir de qualquer exceção, embutida ou própria, e para qualquer exceção. O padrão comum é capturar uma embutida de baixo nível, como KeyError ou ValueError, e levantar uma exceção do seu domínio a partir dela com from.
Fontes
Seu progresso fica salvo neste aparelho. Assinantes sincronizam entre os aparelhos.