09/03/2026, 16:08 Python vs Rust Error Handling
Sou programador Python aprendendo Rust, tenha ótima
didática e faça correlação entre as linguagens, mostre
como o rust trabalha com Error Handling
Pensou por alguns segundos
Claro. Vamos fazer isso do jeito certo: comparando Python com Rust, porque isso acelera
muito o aprendizado quando você já programa bem em Python.
Visão geral
Em Python, tratamento de erro normalmente gira em torno de:
try
except
raise
exceções em tempo de execução
Em Rust, o tratamento de erro é mais explícito, seguro e previsível.
A ideia principal é:
erros esperados → usar Result<T, E>
ausência de valor → usar Option<T>
erros irrecuperáveis → panic!
Ou seja, em Rust você geralmente não “pega exceções” como em Python.
Você modela o erro no tipo de retorno.
1. Comparação mental: Python vs Rust
Python
def dividir(a, b):
return a / b
try:
print(dividir(10, 0))
[Link] 1/19
09/03/2026, 16:08 Python vs Rust Error Handling
except ZeroDivisionError as e:
Python Executar
print(f"Erro: {e}")
Aqui a função não diz no tipo que pode falhar.
Você só descobre isso pela documentação ou pela experiência.
Rust
fn dividir(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err("divisão por zero".to_string())
} else {
Ok(a / b)
}
}
Aqui o tipo já informa:
Ok(f64) → sucesso
Err(String) → falha
Isso força quem chama a função a lidar com o erro.
2. O tipo Result<T, E>
Esse é o coração do error handling em Rust.
Estrutura
enum Result<T, E> {
Ok(T),
Err(E),
}
Rust
Pense assim:
T = tipo do valor de sucesso
E = tipo do erro
Exemplo simples
[Link] 2/19
09/03/2026, 16:08 Python vs Rust Error Handling
fn converter_numero(txt: &str) -> Result<i32, std::num::ParseIntError> {
[Link]::<i32>()
}
Rust
Uso:
fn main() {
let resultado = converter_numero("123");
match resultado {
Ok(valor) => println!("Número convertido: {}", valor),
Err(erro) => println!("Falha ao converter: {}", erro),
}
}
3. Correlação direta com Python
Python: exceção
def converter_numero(txt):
return int(txt)
try:
n = converter_numero("abc")
except ValueError as e:
print("Erro:", e)
Rust: retorno explícito
fn converter_numero(txt: &str) -> Result<i32, std::num::ParseIntError> {
[Link]::<i32>()
}
Rust
Diferença conceitual:
Python: erro “explode” e você captura depois
Rust: erro volta como valor e você decide o que fazer
[Link] 3/19
09/03/2026, 16:08 Python vs Rust Error Handling
Essa diferença é enorme.
Em Rust, erro é dado, não evento excepcional invisível.
4. match : a forma mais explícita de tratar erro
Em Rust, match é o equivalente mental mais forte para “tratar todos os casos”.
fn dividir(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 {
Err("divisão por zero".to_string())
} else {
Ok(a / b)
}
}
fn main() {
match dividir(10.0, 2.0) {
Ok(resultado) => println!("Resultado: {}", resultado),
Err(msg) => println!("Erro: {}", msg),
}
}
Leitura didática
dividir(...) retorna Result
match obriga você a tratar:
Ok(resultado)
Err(msg)
Isso evita esquecer casos de falha.
5. O operador ? : o mais importante para quem vem do
Python
Depois que você entende Result , o próximo passo essencial é o ? .
Ele serve para:
pegar o valor de Ok(...)
ou retornar o erro imediatamente se vier Err(...)
[Link] 4/19
09/03/2026, 16:08 Python vs Rust Error Handling
Exemplo
use std::num::ParseIntError;
fn somar_textos(a: &str, b: &str) -> Result<i32, ParseIntError> {
let x = [Link]::<i32>()?;
let y = [Link]::<i32>()?;
Ok(x + y)
}
fn main() {
match somar_textos("10", "20") {
Ok(soma) => println!("Soma: {}", soma),
Err(e) => println!("Erro: {}", e),
}
}
O que ? faz aqui
let Rust
x = [Link]::<i32>()?;
É quase como se fosse:
let x = match [Link]::<i32>() {
Ok(valor) => valor,
Err(e) => return Err(e),
};
Rust
Correlação com Python
Em Python, você poderia fazer assim:
def somar_textos(a, b):
x = int(a)
y = int(b)
return x + y
Python Executar
Se falhar, sobe exceção.
[Link] 5/19
09/03/2026, 16:08 Python vs Rust Error Handling
Em Rust:
a falha não sobe “misteriosamente”
ela volta pelo Result
o ? simplifica a propagação
6. unwrap() e expect() : use com cuidado
Esses métodos existem, mas você precisa entender quando usar.
unwrap()
fn main() {
let n = "123".parse::<i32>().unwrap();
println!("{}", n);
}
Rust
Se der erro, o programa panica e termina.
expect()
fn main() {
let n = "abc".parse::<i32>().expect("Era esperado um número inteiro válido");
println!("{}", n);
}
Rust
Se falhar, mostra uma mensagem mais clara.
Equivalência mental com Python
É parecido com fazer algo que você assume que sempre vai funcionar, mas sem tratar erro
adequadamente.
Em código Python, seria como:
[Link] 6/19
09/03/2026, 16:08 Python vs Rust Error Handling
n = Python
int("abc") # explode se falhar Executar
Regra prática
Use unwrap() ou expect() quando:
em testes
em protótipos
em casos realmente garantidos
em inicialização de dados fixos que você controla
Evite em código de produção para entradas externas.
7. Option<T> : quando não é erro, é ausência
Nem toda ausência de valor é erro.
Exemplo em Python
def buscar_nome(id_):
banco = {1: "Ana", 2: "Carlos"}
return [Link](id_)
Python Executar
Aqui get pode retornar None .
Em Rust
fn buscar_nome(id: u32) -> Option<&'static str> {
match id {
1 => Some("Ana"),
2 => Some("Carlos"),
_ => None,
}
}
Uso:
[Link] 7/19
09/03/2026, 16:08 Python vs Rust Error Handling
fn main() {
match buscar_nome(3) {
Some(nome) => println!("Nome: {}", nome),
None => println!("Usuário não encontrado"),
}
} Rust
Correlação
Python None
Rust Option
Some(valor)
None
8. Quando usar Option e quando usar Result
Essa parte é crucial.
Use Option quando:
a ausência é normal e esperada.
Exemplos:
procurar chave em mapa
pegar primeiro elemento de lista
buscar item que pode não existir
Use Result quando:
há uma falha que precisa ser explicada.
Exemplos:
erro ao abrir arquivo
erro ao converter string para número
erro de rede
entrada inválida
9. Exemplo real: leitura de arquivo
Python
[Link] 8/19
09/03/2026, 16:08 Python vs Rust Error Handling
def ler_arquivo(caminho):
with open(caminho, "r", encoding="utf-8") as f:
return [Link]()
try:
conteudo = ler_arquivo("[Link]")
print(conteudo)
except FileNotFoundError:
print("Arquivo não encontrado")
except OSError as e:
print("Erro de I/O:", e)
Rust
use std::fs;
use std::io;
fn ler_arquivo(caminho: &str) -> Result<String, io::Error> {
fs::read_to_string(caminho)
}
fn main() {
match ler_arquivo("[Link]") {
Ok(conteudo) => println!("{}", conteudo),
Err(e) => println!("Erro ao ler arquivo: {}", e),
}
}
10. Propagando erro com ? em arquivo
use std::fs;
use std::io;
fn ler_e_contar(caminho: &str) -> Result<usize, io::Error> {
let conteudo = fs::read_to_string(caminho)?;
Ok([Link]().count())
}
fn main() {
[Link] 9/19
09/03/2026, 16:08 Python vs Rust Error Handling
match ler_e_contar("[Link]") {
Ok(qtd) => println!("Linhas: {}", qtd),
Err(e) => println!("Erro: {}", e),
}
}
Explicação
read_to_string(...) retorna Result<String, io::Error>
? pega o String se der certo
se falhar, retorna Err(io::Error) automaticamente
11. Criando seus próprios tipos de erro
Aqui Rust fica muito poderoso.
Forma simples com String
fn validar_idade(idade: i32) -> Result<(), String> {
if idade < 0 {
Err("idade não pode ser negativa".to_string())
} else if idade < 18 {
Err("idade menor que 18".to_string())
} else {
Ok(())
}
}
Isso funciona, mas não é o ideal para sistemas maiores.
Forma melhor com enum
#[derive(Debug)]
enum ErroValidacao {
IdadeNegativa,
MenorDeIdade,
}
fn validar_idade(idade: i32) -> Result<(), ErroValidacao> {
if idade < 0 {
Err(ErroValidacao::IdadeNegativa)
[Link] 10/19
09/03/2026, 16:08 Python vs Rust Error Handling
} else if idade < 18 {
Err(ErroValidacao::MenorDeIdade)
} else {
Ok(())
}
}
fn main() {
match validar_idade(15) {
Ok(()) => println!("Idade válida"),
Err(erro) => println!("Erro: {:?}", erro),
}
}
Correlação com Python
Em Python, você poderia criar exceções customizadas:
class IdadeNegativaError(Exception):
pass
class MenorDeIdadeError(Exception):
pass
P th E t
Em Rust, você normalmente usa enum para representar as variantes do erro.
Isso é muito elegante porque:
é fortemente tipado
é explícito
é fácil usar com match
12. Implementando Display para erro customizado
Para exibir mensagens bonitas:
use std::fmt;
#[derive(Debug)]
enum ErroValidacao {
IdadeNegativa,
[Link] 11/19
09/03/2026, 16:08 Python vs Rust Error Handling
MenorDeIdade,
}
impl fmt::Display for ErroValidacao {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErroValidacao::IdadeNegativa => write!(f, "idade não pode ser negativ
ErroValidacao::MenorDeIdade => write!(f, "usuário deve ser maior de i
}
}
}
fn validar_idade(idade: i32) -> Result<(), ErroValidacao> {
if idade < 0 {
Err(ErroValidacao::IdadeNegativa)
} else if idade < 18 {
Err(ErroValidacao::MenorDeIdade)
} else {
Ok(())
}
}
fn main() {
match validar_idade(10) {
Ok(()) => println!("Tudo certo"),
Err(e) => println!("Erro: {}", e),
}
}
Agora o erro aparece de forma amigável.
13. panic! : erro irrecuperável
panic! encerra o programa.
fn main() {
panic!("algo deu muito errado");
}
Rust
Também acontece implicitamente com unwrap() quando falha.
Quando pensar em panic!
Use quando:
é bug de programação
[Link] 12/19
09/03/2026, 16:08 Python vs Rust Error Handling
estado impossível aconteceu
invariantes internas foram violadas
Não use para fluxo comum de aplicação
Por exemplo:
entrada inválida do usuário
arquivo ausente
falha de rede
Esses casos pedem Result , não panic! .
14. Comparação prática de filosofia
Python
Muito ergonômico, rápido para escrever.
Mas pode esconder caminhos de erro se você não ler a documentação.
Rust
Mais verboso no começo.
Mas te obriga a modelar corretamente o que pode falhar.
Isso reduz uma classe enorme de bugs.
15. Padrão muito comum em Rust
Você verá isso o tempo todo:
fn fazer_algo() -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}
Rust
O que significa
() = sucesso sem valor relevante
Box<dyn Error> = tipo genérico para vários erros
Exemplo:
[Link] 13/19
09/03/2026, 16:08 Python vs Rust Error Handling
use std::fs;
use std::error::Error;
fn processar() -> Result<(), Box<dyn Error>> {
let conteudo = fs::read_to_string("[Link]")?;
let numero: i32 = [Link]().parse()?;
println!("Número: {}", numero);
Ok(())
}
fn main() {
if let Err(e) = processar() {
println!("Erro: {}", e);
}
}
Boa analogia com Python
É parecido com uma função que pode falhar por vários motivos diferentes:
arquivo
parse
formato
Só que em Rust você torna isso explícito no tipo.
16. if let para casos simples
Às vezes match é verboso.
Você pode usar if let .
Exemplo com Result
fn main() {
let resultado = "42".parse::<i32>();
if let Ok(numero) = resultado {
println!("Número: {}", numero);
} else {
println!("Falhou");
}
}
[Link] 14/19
09/03/2026, 16:08 Python vs Rust Error Handling
Exemplo com Option
fn main() {
let nome = Some("Gandra");
if let Some(n) = nome {
println!("Olá, {}", n);
}
}
17. Resumo mental para decorar
Guarde isso:
Em Python
erro costuma ser tratado com try/except
exceções podem surgir “depois”
Em Rust
erro esperado = Result<T, E>
ausência = Option<T>
falha fatal = panic!
propagação elegante = ?
18. Exemplo lado a lado: Python e Rust
Python
def ler_numero_arquivo(caminho):
with open(caminho, "r", encoding="utf-8") as f:
return int([Link]().strip())
try:
n = ler_numero_arquivo("[Link]")
print(n)
except FileNotFoundError:
print("Arquivo não encontrado")
except ValueError:
[Link] 15/19
09/03/2026, 16:08 Python vs Rust Error Handling
print("Conteúdo inválido")
except OSError as e:
print("Erro de I/O:", e)
Rust
use std::fs;
use std::error::Error;
fn ler_numero_arquivo(caminho: &str) -> Result<i32, Box<dyn Error>> {
let conteudo = fs::read_to_string(caminho)?;
let numero = [Link]().parse::<i32>()?;
Ok(numero)
}
fn main() {
match ler_numero_arquivo("[Link]") {
Ok(n) => println!("{}", n),
Err(e) => println!("Erro: {}", e),
}
}
19. O que mais confunde quem vem do Python
Aqui estão os pontos que mais pegam:
1. “Por que Rust não usa exceção igual Python?”
Porque Rust quer que o compilador ajude a garantir que você tratou falhas possíveis.
2. “Tudo vira Result ?”
Não tudo. Só o que pode falhar de forma esperada.
3. “Então panic! é igual exception?”
Não exatamente. panic! é mais próximo de um aborto controlado por erro grave.
4. “ ? é tipo try/except?”
Não.
Ele é mais um atalho para propagação de erro.
[Link] 16/19
09/03/2026, 16:08 Python vs Rust Error Handling
20. Regra de ouro para pensar como Rustacean
Quando criar uma função, pergunte:
A falta de valor é normal?
Use Option<T> .
A falha precisa de explicação?
Use Result<T, E> .
Isso representa bug ou estado impossível?
Use panic! apenas se fizer sentido.
21. Exemplo final, bem idiomático
use std::fs;
use std::error::Error;
fn carregar_idade(caminho: &str) -> Result<u8, Box<dyn Error>> {
let conteudo = fs::read_to_string(caminho)?;
let idade: u8 = [Link]().parse()?;
if idade > 130 {
return Err("idade inválida: maior que 130".into());
}
Ok(idade)
}
fn main() {
match carregar_idade("[Link]") {
Ok(idade) => println!("Idade carregada: {}", idade),
Err(e) => eprintln!("Falha ao carregar idade: {}", e),
}
}
O que esse exemplo mostra
leitura de arquivo pode falhar
conversão para número pode falhar
validação de domínio também pode falhar
tudo isso é encadeado com Result
[Link] 17/19
09/03/2026, 16:08 Python vs Rust Error Handling
22. Mapa mental final
Python
try/except
raise
exceptions em runtime
Rust
Result<T, E> -> erro esperado
Option<T> -> ausência de valor
? -> propaga erro
match -> trata explicitamente
unwrap/expect -> falha imediata
panic! -> erro irrecuperável
23. Conselho prático para você evoluir rápido
Como você já programa em Python, a melhor estratégia é esta:
1. pare de pensar em exceção
2. pense em tipo de retorno
3. ao escrever função em Rust, sempre pergunte:
pode faltar valor?
pode falhar?
esse erro deve subir?
4. use match no começo
5. depois migre para ? quando entender bem
Essa transição é o ponto em que Rust começa a “clicar” na mente de quem vem do
Python.
24. Exercício ideal para treinar
Implemente em Rust estas 3 funções:
ler um arquivo texto
converter conteúdo para inteiro
dividir 100 por esse inteiro
E trate os casos:
[Link] 18/19
09/03/2026, 16:08 Python vs Rust Error Handling
arquivo não existe
conteúdo inválido
divisão por zero
Isso vai te obrigar a usar:
Result
match
erro de domínio
Se você quiser, no próximo passo eu posso montar para você um mini projeto em Rust
comparado com Python, mostrando Result , Option , match , ? , unwrap , expect e
erro customizado em um exemplo único e progressivo.
[Link] 19/19