0% acharam este documento útil (0 voto)
5 visualizações38 páginas

Error Handling Python Vs Rust

O documento compara o tratamento de erros em Python e Rust, destacando que Python utiliza exceções enquanto Rust emprega tipos explícitos como Result<T, E> e Option<T>. Ele explora conceitos fundamentais como a diferença entre erros esperados e bugs, quando usar Option ou Result, e apresenta exemplos práticos de tratamento de erros em ambas as linguagens. Além disso, discute a criação de erros personalizados e a implementação de tipos de erro que se integram ao ecossistema Rust.
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
5 visualizações38 páginas

Error Handling Python Vs Rust

O documento compara o tratamento de erros em Python e Rust, destacando que Python utiliza exceções enquanto Rust emprega tipos explícitos como Result<T, E> e Option<T>. Ele explora conceitos fundamentais como a diferença entre erros esperados e bugs, quando usar Option ou Result, e apresenta exemplos práticos de tratamento de erros em ambas as linguagens. Além disso, discute a criação de erros personalizados e a implementação de tipos de erro que se integram ao ecossistema Rust.
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd

11/03/2026, 12:48 Error Handling Python vs Rust

ChatGPT 5.4 Thinking Memória desativada

Sou programador Python aprendendo Rust, tenha ótima


didática e faça correlação entre as linguagens, mostre
como o rust trabalha comSou programador Python
aprendendo Rust, tenha ótima didática e faça correlação
entre as linguagens, mostre como o rust trabalha com
Error Handling Profissional (faça bem detalhado, com
todas as possibilidades, tipos diferente de executar esse
tipo de verificação, mostre muitos exemplos com paralelos
em python)

Pensou por alguns segundos

Perfeito. Vou te explicar Error Handling profissional em Rust fazendo paralelo com
Python o tempo todo, porque isso acelera muito a curva de aprendizado.

Visão geral: Python vs Rust no tratamento de erros


Em Python, o fluxo clássico é:

Python Executar

try:
valor = int("123")
except ValueError as e:
print(f"Erro: {e}")

Em Rust, o fluxo idiomático geralmente é:

Rust

let valor: i32 = "123".parse()?;

A grande diferença é esta:


Python trata erros principalmente com exceptions ( try/except )
Rust trata erros principalmente com tipos explícitos, especialmente:
Result<T, E>

Option<T>

[Link] 1/38
11/03/2026, 12:48 Error Handling Python vs Rust

Ou seja, em Rust o erro faz parte da assinatura da função e do tipo retornado.


Isso força o código a deixar claro onde algo pode falhar.

1) Os dois pilares do error handling em Rust


Option<T>
Representa:
Some(valor) → existe valor

None → não existe valor

Use quando não há valor, mas isso não é exatamente um erro operacional.

Exemplo em Python

Python Executar

def buscar_usuario(dic, chave):


return [Link](chave) # retorna None se não achar

Equivalente em Rust

Rust

fn buscar_usuario(dic: &std::collections::HashMap<String, String>, chave: &str) -


[Link](chave).cloned()
}

 

Result<T, E>
Representa:

Ok(valor) → sucesso
Err(erro) → falha

Use quando houve uma falha real que precisa ser tratada.

Exemplo em Python

Python Executar

[Link] 2/38
11/03/2026, 12:48 Error Handling Python vs Rust

def dividir(a, b):


if b == 0:
raise ZeroDivisionError("divisão por zero")
return a / b

Equivalente em Rust

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)
}
}

2) Mentalidade correta: erro esperado vs bug


Essa separação em Rust é muito importante.

Erro esperado
É algo normal do mundo real:
arquivo não existe
input inválido
parse falhou
conexão recusada
JSON malformado

Isso normalmente vira Result .

Ausência esperada
Também normal:
chave não encontrada
item opcional não existe
campo pode ser vazio

Isso normalmente vira Option .

Bug / invariável quebrada


É quando o programa chegou num estado impossível.

[Link] 3/38
11/03/2026, 12:48 Error Handling Python vs Rust

Exemplo:

índice impossível por lógica interna


valor que “nunca deveria ser None”
contrato interno violado

Nesse caso, pode haver:

panic!
unwrap() em contexto muito controlado

expect() com mensagem clara

3) Quando usar Option e quando usar Result


Use Option quando:
não encontrar valor é aceitável
não quer descrever motivo detalhado
ausência é parte normal do fluxo

Exemplo

Rust

fn primeiro_nome(nome_completo: &str) -> Option<&str> {


nome_completo.split_whitespace().next()
}

Use Result quando:


a causa da falha importa
precisa propagar erro
falha operacional precisa contexto

Exemplo

Rust

fn ler_idade(texto: &str) -> Result<u32, std::num::ParseIntError> {


[Link]::<u32>()
}

[Link] 4/38
11/03/2026, 12:48 Error Handling Python vs Rust

4) Tratamento básico com match


match é o equivalente mais explícito e robusto.

Result

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)
}
}

fn main() {
match dividir(10.0, 2.0) {
Ok(resultado) => println!("Resultado: {}", resultado),
Err(erro) => println!("Erro: {}", erro),
}
}

Paralelo em Python

Python Executar

try:
resultado = dividir(10, 2)
print(resultado)
except Exception as e:
print(e)

Option

Rust

fn main() {
let nome = Some("Gandra");

match nome {
Some(valor) => println!("Nome: {}", valor),
None => println!("Sem nome"),
}
}

[Link] 5/38
11/03/2026, 12:48 Error Handling Python vs Rust

5) Métodos úteis de Option


unwrap_or
Fornece valor padrão.

Rust

let nome = None;


let valor = nome.unwrap_or("Desconhecido");
println!("{}", valor);

Python

Python Executar

nome = None
valor = nome or "Desconhecido"

unwrap_or_else
Calcula o fallback sob demanda.

Rust

let nome: Option<String> = None;


let valor = nome.unwrap_or_else(|| "Desconhecido".to_string());

map
Transforma o conteúdo se existir.

Rust

let nome = Some("gandra");


let maiusculo = [Link](|s| s.to_uppercase());
println!("{:?}", maiusculo);

Python

Python Executar

[Link] 6/38
11/03/2026, 12:48 Error Handling Python vs Rust

nome = "gandra"
maiusculo = [Link]() if nome is not None else None

and_then
Encadeia operações que também retornam Option .

Rust

fn primeiro_token(s: &str) -> Option<&str> {


s.split_whitespace().next()
}

fn primeira_letra(s: &str) -> Option<char> {


[Link]().next()
}

let resultado = primeiro_token("rust language").and_then(primeira_letra);


println!("{:?}", resultado); // Some('r')

ok_or / ok_or_else
Converte Option em Result .

Rust

fn buscar_porta(env: Option<String>) -> Result<String, String> {


env.ok_or_else(|| "PORT não configurada".to_string())
}

Isso é muito usado em código profissional.

6) Métodos úteis de Result


unwrap
Extrai valor ou dá panic!

Rust

let n: i32 = "42".parse().unwrap();

[Link] 7/38
11/03/2026, 12:48 Error Handling Python vs Rust

Equivalente mental em Python


Seria como assumir que nada dará errado e deixar estourar exception.

Em produção, use com muito cuidado.

expect
Mesmo comportamento, mas com mensagem melhor.

Rust

let n: i32 = "42".parse().expect("Falha ao converter string para i32");

Melhor que unwrap() , porque a mensagem ajuda no diagnóstico.

unwrap_or

Rust

let n: i32 = "abc".parse().unwrap_or(0);


println!("{}", n); // 0

unwrap_or_else

Rust

let n: i32 = "abc".parse().unwrap_or_else(|err| {


eprintln!("Erro de parse: {}", err);
0
});

map
Transforma Ok .

Rust

let valor = "10".parse::<i32>().map(|n| n * 2);

[Link] 8/38
11/03/2026, 12:48 Error Handling Python vs Rust

println!("{:?}", valor); // Ok(20)

map_err
Transforma Err .

Rust

let valor = "abc"


.parse::<i32>()
.map_err(|e| format!("Erro ao converter idade: {}", e));

println!("{:?}", valor);

and_then
Encadeia operações que retornam Result .

Rust

fn parse_num(s: &str) -> Result<i32, std::num::ParseIntError> {


[Link]::<i32>()
}

fn validar_positivo(n: i32) -> Result<i32, String> {


if n > 0 {
Ok(n)
} else {
Err("Número deve ser positivo".to_string())
}
}

fn main() {
let resultado = parse_num("10")
.map_err(|e| e.to_string())
.and_then(validar_positivo);

println!("{:?}", resultado);
}

7) O operador ? : a forma idiomática profissional


Esse é um dos recursos mais importantes.
[Link] 9/38
11/03/2026, 12:48 Error Handling Python vs Rust

Ideia
Se der Ok , segue.
Se der Err , retorna imediatamente o erro para o chamador.

Exemplo

Rust

use std::num::ParseIntError;

fn somar_strings(a: &str, b: &str) -> Result<i32, ParseIntError> {


let x: i32 = [Link]()?;
let y: i32 = [Link]()?;
Ok(x + y)
}

Sem ?

Rust

use std::num::ParseIntError;

fn somar_strings(a: &str, b: &str) -> Result<i32, ParseIntError> {


let x = match [Link]::<i32>() {
Ok(v) => v,
Err(e) => return Err(e),
};

let y = match [Link]::<i32>() {


Ok(v) => v,
Err(e) => return Err(e),
};

Ok(x + y)
}

Paralelo em Python
É como se cada linha pudesse automaticamente “subir” a exception sem escrever
try/except ali.

Python Executar

def somar_strings(a, b):


x = int(a)
y = int(b)
return x + y

[Link] 10/38
11/03/2026, 12:48 Error Handling Python vs Rust

Em Python, a exception sobe implicitamente.


Em Rust, isso acontece explicitamente com ? .

8) ? com Option
Também funciona com Option .

Rust

fn primeira_letra_do_primeiro_nome(s: &str) -> Option<char> {


let primeiro_nome = s.split_whitespace().next()?;
let primeira_letra = primeiro_nome.chars().next()?;
Some(primeira_letra)
}

Se qualquer passo falhar, retorna None .

9) Criando erros simples com String e &str


No começo, muita gente faz isso:

Rust

fn validar_usuario(nome: &str) -> Result<(), String> {


if [Link]().is_empty() {
Err("Nome não pode ser vazio".to_string())
} else {
Ok(())
}
}

Funciona.
É bom para exemplos, protótipos e pequenos utilitários.

Mas em código profissional maior, normalmente preferimos tipos de erro próprios.

10) Erros customizados: abordagem profissional


Aqui começa o nível mais sério.

Exemplo com enum própria

[Link] 11/38
11/03/2026, 12:48 Error Handling Python vs Rust

Rust

use std::fmt;

#[derive(Debug)]
enum ErroCadastro {
NomeVazio,
IdadeInvalida,
IdadeNegativa,
}

impl fmt::Display for ErroCadastro {


fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErroCadastro::NomeVazio => write!(f, "nome não pode ser vazio"),
ErroCadastro::IdadeInvalida => write!(f, "idade inválida"),
ErroCadastro::IdadeNegativa => write!(f, "idade não pode ser negativa
}
}
}

fn cadastrar(nome: &str, idade_str: &str) -> Result<(), ErroCadastro> {


if [Link]().is_empty() {
return Err(ErroCadastro::NomeVazio);
}

let idade: i32 = idade_str.parse().map_err(|_| ErroCadastro::IdadeInvalida)?;

if idade < 0 {
return Err(ErroCadastro::IdadeNegativa);
}

Ok(())
}

 

Por que isso é melhor?


Porque o erro deixa de ser texto solto e vira tipo estruturado.

Você pode:

casar com match


categorizar falhas
testar facilmente
decidir ações diferentes por tipo de erro

[Link] 12/38
11/03/2026, 12:48 Error Handling Python vs Rust

Paralelo com Python


Em Python profissional você faria classes de exception:

Python Executar

class NomeVazioError(Exception):
pass

class IdadeInvalidaError(Exception):
pass

class IdadeNegativaError(Exception):
pass

Em Rust, a enum concentra tudo em um tipo seguro e explícito.

11) Implementando std::error::Error


Se quiser que seu erro se integre melhor ao ecossistema:

Rust

use std::error::Error;
use std::fmt;

#[derive(Debug)]
enum MeuErro {
FalhaParse,
}

impl fmt::Display for MeuErro {


fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
MeuErro::FalhaParse => write!(f, "falha de parse"),
}
}
}

impl Error for MeuErro {}

Isso é importante quando você quer interoperar com bibliotecas e com tipos genéricos de
erro.

12) Encadeamento e conversão de erros com From


[Link] 13/38
11/03/2026, 12:48 Error Handling Python vs Rust

Esse é um ponto muito forte de Rust.

Problema
Sua função chama várias operações que retornam erros diferentes:

std::io::Error
serde_json::Error

ParseIntError

Você quer retornar um único tipo de erro da aplicação.

Solução
Criar enum e implementar From .

Rust

use std::fmt;
use std::io;
use std::num::ParseIntError;

#[derive(Debug)]
enum AppError {
Io(io::Error),
Parse(ParseIntError),
}

impl fmt::Display for AppError {


fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AppError::Io(e) => write!(f, "erro de I/O: {}", e),
AppError::Parse(e) => write!(f, "erro de parse: {}", e),
}
}
}

impl std::error::Error for AppError {}

impl From<io::Error> for AppError {


fn from(err: io::Error) -> Self {
AppError::Io(err)
}
}

impl From<ParseIntError> for AppError {


fn from(err: ParseIntError) -> Self {
AppError::Parse(err)
}
}

[Link] 14/38
11/03/2026, 12:48 Error Handling Python vs Rust

Agora o ? converte automaticamente:

Rust

use std::fs;

fn ler_numero_arquivo(path: &str) -> Result<i32, AppError> {


let conteudo = fs::read_to_string(path)?; // io::Error -> AppError
let numero = [Link]().parse::<i32>()?; // ParseIntError -> AppError
Ok(numero)
}

13) Box<dyn Error> : abordagem genérica


Muito usada em exemplos e CLIs simples.

Rust

use std::error::Error;
use std::fs;

fn ler_numero(path: &str) -> Result<i32, Box<dyn Error>> {


let conteudo = fs::read_to_string(path)?;
let numero = [Link]().parse::<i32>()?;
Ok(numero)
}

Vantagens
rápido de escrever
aceita muitos tipos de erro
bom para utilitários simples

Desvantagens
perde parte da tipagem específica
menos controle para tratamento detalhado
menos expressivo para domínio de negócio

Regra prática
app pequena / CLI / protótipo: Box<dyn Error> pode ser aceitável
biblioteca / sistema maior / domínio rico: prefira erro customizado

[Link] 15/38
11/03/2026, 12:48 Error Handling Python vs Rust

14) Bibliotecas profissionais: thiserror e anyhow


Essas são extremamente comuns.

thiserror
Ótima para criar erros tipados de biblioteca/aplicação.

[Link]

TOML

[dependencies]
thiserror = "2"

Exemplo

Rust

use thiserror::Error;
use std::num::ParseIntError;
use std::io;

#[derive(Debug, Error)]
enum AppError {
#[error("erro de I/O: {0}")]
Io(#[from] io::Error),

#[error("erro de parse: {0}")]


Parse(#[from] ParseIntError),

#[error("campo vazio: {0}")]


CampoVazio(String),
}

Uso:

Rust

use std::fs;

fn processar(path: &str) -> Result<i32, AppError> {


let conteudo = fs::read_to_string(path)?;
if [Link]().is_empty() {
return Err(AppError::CampoVazio("arquivo".to_string()));
}
let valor = [Link]().parse::<i32>()?;

[Link] 16/38
11/03/2026, 12:48 Error Handling Python vs Rust

Ok(valor)
}

Vantagens
menos boilerplate
claro e profissional
ideal para erros tipados

anyhow
Muito boa para aplicações, CLIs e código de alto nível.

[Link]

TOML

[dependencies]
anyhow = "1"

Exemplo

Rust

use anyhow::{Context, Result};


use std::fs;

fn processar(path: &str) -> Result<i32> {


let conteudo = fs::read_to_string(path)
.with_context(|| format!("falha ao ler arquivo {}", path))?;

let valor = conteudo


.trim()
.parse::<i32>()
.context("falha ao converter conteúdo para i32")?;

Ok(valor)
}

Vantagens
ergonomia excelente
adiciona contexto facilmente
ótimo para binários executáveis
muito produtivo

[Link] 17/38
11/03/2026, 12:48 Error Handling Python vs Rust

Desvantagens
não é ideal para API pública de biblioteca
apaga parte da taxonomia precisa do erro

Regra de ouro: thiserror vs anyhow

Use thiserror quando:


está escrevendo biblioteca
quer erro fortemente tipado
o chamador precisa distinguir tipos de erro

Use anyhow quando:


está escrevendo aplicação
quer rapidez e bom contexto
não precisa expor taxonomia rígida

Paralelo em Python
thiserror lembra criar classes específicas de exception

anyhow lembra uma abordagem mais pragmática de subir exceções enriquecidas

com contexto/log

15) Adicionando contexto ao erro


Isso é profissional demais e muita gente negligencia.

Erro ruim:

“invalid digit found in string”

Erro bom:
“falha ao converter campo idade do arquivo [Link]: invalid digit found in string”

Sem biblioteca

Rust

fn parse_idade(s: &str) -> Result<u32, String> {


[Link]::<u32>()

[Link] 18/38
11/03/2026, 12:48 Error Handling Python vs Rust

.map_err(|e| format!("falha ao converter idade '{}': {}", s, e))


}

Com anyhow

Rust

use anyhow::{Context, Result};

fn parse_idade(s: &str) -> Result<u32> {


[Link]::<u32>()
.with_context(|| format!("falha ao converter idade '{}'", s))
}

16) panic! , unwrap() , expect() : quando usar e quando


evitar
panic!
Interrompe o programa imediatamente.

Rust

panic!("estado impossível");

unwrap()
Se falhar, chama panic.

Rust

let x = Some(10).unwrap();

expect()
Mesma ideia, mas com mensagem sua.

Rust

let x = Some(10).expect("valor obrigatório ausente");

Quando é aceitável usar


[Link] 19/38
11/03/2026, 12:48 Error Handling Python vs Rust

1. Testes

Rust

#[test]
fn teste_parse() {
let n: i32 = "42".parse().unwrap();
assert_eq!(n, 42);
}

2. Protótipos rápidos

3. Invariáveis internas muito fortes

4. Inicialização onde falhar deve abortar


Exemplo: configuração essencial impossível de continuar sem ela.

Quando evitar
em entrada do usuário
I/O
rede
banco de dados
parsing externo
qualquer coisa sujeita ao mundo real

Regra prática
Se o erro pode acontecer por ação normal do usuário ou do ambiente, não use unwrap() .

17) main retornando Result


Isso é muito idiomático.

Rust

use std::error::Error;
use std::fs;

fn main() -> Result<(), Box<dyn Error>> {


let conteudo = fs::read_to_string("[Link]")?;
println!("{}", conteudo);

[Link] 20/38
11/03/2026, 12:48 Error Handling Python vs Rust

Ok(())
}

Muito melhor do que entupir o main de match .

Paralelo em Python
Seria como deixar a exception propagar até o topo, mas em Rust isso fica explícito e
elegante.

18) Tratamento local vs propagação


Essa é uma decisão arquitetural importante.

Trate localmente quando:


você sabe recuperar
quer fallback
quer transformar erro em comportamento alternativo

Rust

use std::fs;

fn ler_config() -> String {


fs::read_to_string("[Link]").unwrap_or_else(|_| "modo=default".to_string(
}

 

Propague quando:
o chamador tem mais contexto
você não consegue decidir a ação correta
quer manter camada limpa

Rust

use std::fs;
use std::io;

fn ler_config() -> Result<String, io::Error> {


fs::read_to_string("[Link]")
}

[Link] 21/38
11/03/2026, 12:48 Error Handling Python vs Rust

Regra profissional
Camadas baixas propagam. Camadas altas decidem.

Isso vale muito em Rust e também em Python.

19) Padrões profissionais por tipo de projeto


Biblioteca
evite panic! para erro operacional
exponha Result<T, SeuErro>
use thiserror
documente cada tipo de erro

CLI
use anyhow
adicione contexto
mostre mensagem amigável no topo
logue detalhes se necessário

API/web backend
erros internos separados de erros públicos
mapeie erro de domínio para HTTP status
nunca exponha detalhes sensíveis

Sistemas embarcados / alta confiabilidade


minimizar panic!
preferir estados explícitos
tratar falhas de hardware/comunicação cuidadosamente
considerar custo de alocação e no_std quando aplicável

20) Exemplo real: lendo arquivo e validando conteúdo


Vou montar um exemplo completo.

Versão Python

Python Executar

[Link] 22/38
11/03/2026, 12:48 Error Handling Python vs Rust

def carregar_porta(caminho: str) -> int:


with open(caminho, "r", encoding="utf-8") as f:
conteudo = [Link]().strip()

porta = int(conteudo)

if not (1 <= porta <= 65535):


raise ValueError("porta fora do intervalo válido")

return porta

Versão Rust simples

Rust

use std::fs;
use std::num::ParseIntError;

#[derive(Debug)]
enum ConfigError {
Io(std::io::Error),
Parse(ParseIntError),
FaixaInvalida(u16),
}

impl std::fmt::Display for ConfigError {


fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ConfigError::Io(e) => write!(f, "erro ao ler arquivo: {}", e),
ConfigError::Parse(e) => write!(f, "erro ao converter porta: {}", e),
ConfigError::FaixaInvalida(p) => write!(f, "porta {} fora da faixa vá
}
}
}

impl std::error::Error for ConfigError {}

impl From<std::io::Error> for ConfigError {


fn from(err: std::io::Error) -> Self {
ConfigError::Io(err)
}
}

impl From<ParseIntError> for ConfigError {


fn from(err: ParseIntError) -> Self {
ConfigError::Parse(err)
}
}

[Link] 23/38
11/03/2026, 12:48 Error Handling Python vs Rust

fn carregar_porta(caminho: &str) -> Result<u16, ConfigError> {


let conteudo = fs::read_to_string(caminho)?;
let porta: u16 = [Link]().parse()?;

if !(1..=65535).contains(&porta) {
return Err(ConfigError::FaixaInvalida(porta));
}

Ok(porta)
}

21) Armadilha importante: u16 já impede negativos


Veja esse detalhe: se você fizer:

Rust

let porta: u16 = [Link]().parse()?;

o próprio parse já falha para:

-1

70000

abc

Ou seja, às vezes o tipo já valida parte do domínio.

Isso é muito Rust.

Python
Em Python, int aceita muita coisa e a validação costuma vir depois.

Rust
Em Rust, escolher o tipo certo já elimina classes inteiras de erro.

Essa é uma das maiores mudanças de mentalidade para quem vem de Python.

22) if let e while let para casos mais simples


if let
Quando você só quer tratar um caso.

[Link] 24/38
11/03/2026, 12:48 Error Handling Python vs Rust

Rust

let resultado = "42".parse::<i32>();

if let Ok(n) = resultado {


println!("Número: {}", n);
}

Python
Seria algo parecido com tratar apenas o sucesso, mas Python não tem uma sintaxe
equivalente tão natural.

while let
Útil para consumir fluxo opcional.

Rust

let mut pilha = vec![1, 2, 3];

while let Some(valor) = [Link]() {


println!("{}", valor);
}

23) Pattern matching com guardas

Rust

fn classificar(resultado: Result<i32, String>) {


match resultado {
Ok(n) if n > 0 => println!("positivo: {}", n),
Ok(0) => println!("zero"),
Ok(n) => println!("negativo: {}", n),
Err(e) => println!("erro: {}", e),
}
}

Muito útil para tratamento refinado.

24) Coletando vários Result


[Link] 25/38
11/03/2026, 12:48 Error Handling Python vs Rust

Esse é um padrão forte.

Exemplo
Converter várias strings em números.

Rust

fn main() {
let entradas = vec!["1", "2", "3"];

let numeros: Result<Vec<i32>, _> = entradas


.into_iter()
.map(|s| [Link]::<i32>())
.collect();

println!("{:?}", numeros);
}

Se qualquer parse falhar, o collect retorna o primeiro erro.

Paralelo em Python
Em Python você geralmente faria loop com try/except .

Exemplo com erro

Rust

fn main() {
let entradas = vec!["1", "abc", "3"];

let numeros: Result<Vec<i32>, _> = entradas


.into_iter()
.map(|s| [Link]::<i32>())
.collect();

match numeros {
Ok(v) => println!("{:?}", v),
Err(e) => println!("Erro: {}", e),
}
}

25) Ignorando falhas individuais

[Link] 26/38
11/03/2026, 12:48 Error Handling Python vs Rust

Às vezes você quer só os válidos.

Rust

fn main() {
let entradas = vec!["1", "abc", "3"];

let numeros: Vec<i32> = entradas


.into_iter()
.filter_map(|s| [Link]::<i32>().ok())
.collect();

println!("{:?}", numeros); // [1, 3]


}

Python

Python Executar

entradas = ["1", "abc", "3"]


numeros = []

for s in entradas:
try:
[Link](int(s))
except ValueError:
pass

26) Separando sucessos e falhas

Rust

let entradas = vec!["10", "abc", "30"];

let resultados: Vec<Result<i32, _>> =


entradas.into_iter().map(|s| [Link]::<i32>()).collect();

for r in resultados {
match r {
Ok(v) => println!("Ok: {}", v),
Err(e) => println!("Erro: {}", e),
}
}

Isso é útil em pipelines de processamento.

[Link] 27/38
11/03/2026, 12:48 Error Handling Python vs Rust

27) Transformando Option em fluxo de erro


Exemplo comum: campo obrigatório ausente.

Rust

fn obter_email(email: Option<String>) -> Result<String, String> {


email.ok_or_else(|| "email é obrigatório".to_string())
}

Isso aparece muito em:


configs
JSON
formulários
variáveis de ambiente

28) Erros em parsing de domínio


Exemplo: converter string em enum.

Rust

#[derive(Debug)]
enum Ambiente {
Dev,
Prod,
}

impl std::str::FromStr for Ambiente {


type Err = String;

fn from_str(s: &str) -> Result<Self, Self::Err> {


match s {
"dev" => Ok(Ambiente::Dev),
"prod" => Ok(Ambiente::Prod),
_ => Err(format!("ambiente inválido: {}", s)),
}
}
}

Uso:

Rust

fn main() {
let amb: Result<Ambiente, _> = "dev".parse();
[Link] 28/38
11/03/2026, 12:48 Error Handling Python vs Rust

println!("{:?}", amb);
}

Paralelo em Python

Python Executar

from enum import Enum

class Ambiente(Enum):
DEV = "dev"
PROD = "prod"

def parse_ambiente(s: str) -> Ambiente:


try:
return Ambiente(s)
except ValueError:
raise ValueError(f"ambiente inválido: {s}")

29) Error handling em camadas


Essa é uma visão profissional de arquitetura.

Camada de infraestrutura
Lê arquivo, banco, rede.

Rust

fn ler_arquivo(path: &str) -> Result<String, std::io::Error> {


std::fs::read_to_string(path)
}

Camada de domínio
Valida regra de negócio.

Rust

#[derive(Debug)]
enum DominioErro {
NomeVazio,
}

Camada de aplicação

[Link] 29/38
11/03/2026, 12:48 Error Handling Python vs Rust

Orquestra tudo e converte erros.

Rust

#[derive(Debug)]
enum AppError {
Io(std::io::Error),
Dominio(DominioErro),
}

Ideia central
Não misture tudo num erro genérico cedo demais.
Preserve o máximo de estrutura, e só simplifique perto da borda do sistema.

30) Logging + error handling


Tratamento de erro não é só retornar Err .
Também envolve observabilidade.

Em aplicação real:

retorna erro apropriado


adiciona contexto
registra log útil
não expõe segredo

Exemplo conceitual:

Rust

fn processar_usuario(id: &str) -> Result<(), AppError> {


let id_num: u64 = [Link]().map_err(AppError::from)?;
println!("Processando usuário {}", id_num);
Ok(())
}

Em produção, você combinaria isso com logs estruturados.

31) Erro recuperável vs irrecuperável


Rust separa muito bem isso.

[Link] 30/38
11/03/2026, 12:48 Error Handling Python vs Rust

Recuperável
Result , Option

Irrecuperável
panic!

Isso melhora robustez porque o programa força você a pensar:

posso me recuperar?
devo propagar?
isso é bug?

Python deixa isso mais flexível, mas também mais fácil de virar bagunça.

32) O estilo “Pythonista iniciante em Rust” que você deve


evitar
Anti-padrão 1: usar unwrap() em tudo

Rust

let conteudo = std::fs::read_to_string("[Link]").unwrap();

Errado para produção.

Anti-padrão 2: transformar tudo em String cedo demais

Rust

fn processar() -> Result<(), String> {


std::fs::read_to_string("[Link]").map_err(|e| e.to_string())?;
Ok(())
}

Você perde estrutura de erro.

Anti-padrão 3: capturar erro cedo sem necessidade


Se não sabe o que fazer com o erro, propague com ? .

[Link] 31/38
11/03/2026, 12:48 Error Handling Python vs Rust

Anti-padrão 4: usar panic! para erro de entrada do usuário


Usuário digitou errado? Isso não é bug do programa.

33) O estilo profissional recomendado


Em biblioteca

Rust

pub fn executar(...) -> Result<T, MeuErro>

Em app

Rust

fn main() -> anyhow::Result<()>

Em trechos internos
? para propagar

map_err para converter


context para enriquecer

match quando a decisão depende do tipo de erro


expect apenas quando a falha realmente indica bug/configuração fatal

34) Comparação direta com Python


Python

Python Executar

def carregar_idade(texto: str) -> int:


try:
idade = int(texto)
except ValueError as e:
raise ValueError(f"idade inválida: {texto}") from e

if idade < 0:
raise ValueError("idade não pode ser negativa")

[Link] 32/38
11/03/2026, 12:48 Error Handling Python vs Rust

return idade

Rust

Rust

#[derive(Debug)]
enum IdadeErro {
Parse(std::num::ParseIntError),
Negativa,
}

impl std::fmt::Display for IdadeErro {


fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
IdadeErro::Parse(e) => write!(f, "idade inválida: {}", e),
IdadeErro::Negativa => write!(f, "idade não pode ser negativa"),
}
}
}

impl std::error::Error for IdadeErro {}

impl From<std::num::ParseIntError> for IdadeErro {


fn from(e: std::num::ParseIntError) -> Self {
IdadeErro::Parse(e)
}
}

fn carregar_idade(texto: &str) -> Result<i32, IdadeErro> {


let idade: i32 = [Link]()?;
if idade < 0 {
return Err(IdadeErro::Negativa);
}
Ok(idade)
}

35) Exemplo completo com anyhow para aplicação

Rust

use anyhow::{Context, Result};


use std::fs;

fn carregar_idade_do_arquivo(path: &str) -> Result<u32> {


let conteudo = fs::read_to_string(path)

[Link] 33/38
11/03/2026, 12:48 Error Handling Python vs Rust

.with_context(|| format!("não foi possível ler o arquivo '{}'", path))?;

let idade = conteudo


.trim()
.parse::<u32>()
.with_context(|| format!("conteúdo inválido no arquivo '{}'", path))?;

Ok(idade)
}

fn main() -> Result<()> {


let idade = carregar_idade_do_arquivo("[Link]")?;
println!("Idade: {}", idade);
Ok(())
}

Esse estilo é muito usado em CLI e automação.

36) Exemplo completo com thiserror para biblioteca

Rust

use thiserror::Error;
use std::fs;
use std::num::ParseIntError;

#[derive(Debug, Error)]
pub enum ConfigError {
#[error("erro de I/O: {0}")]
Io(#[from] std::io::Error),

#[error("erro de parse do campo porta: {0}")]


Parse(#[from] ParseIntError),

#[error("porta fora do intervalo válido: {0}")]


PortaInvalida(u32),
}

pub fn carregar_porta(path: &str) -> Result<u16, ConfigError> {


let conteudo = fs::read_to_string(path)?;
let porta = [Link]().parse::<u32>()?;

if !(1..=65535).contains(&porta) {
return Err(ConfigError::PortaInvalida(porta));
}

[Link] 34/38
11/03/2026, 12:48 Error Handling Python vs Rust

Ok(porta as u16)
}

37) Como pensar como engenheiro ao tratar erros em


Rust
Quando estiver escrevendo uma função, faça estas perguntas:

1. A ausência de valor é normal?


sim → Option
não → Result

2. O chamador precisa saber o motivo da falha?


sim → erro tipado
não tanto → talvez anyhow em app

3. Esse erro é recuperável?


sim → Result
não, é bug/invariante quebrada → panic! / expect

4. Estou escrevendo biblioteca ou aplicação?


biblioteca → thiserror / tipo próprio
aplicação → anyhow pode ser melhor

5. Estou adicionando contexto suficiente?


Erro sem contexto costuma atrasar debugging.

38) Resumo mental em uma tabela


Situação Python Rust

Ausência normal None Option<T>

Falha recuperável raise Exception Result<T, E>

Propagar erro exception sobe ?

Erro tipado subclasses de Exception enum + Error

[Link] 35/38
11/03/2026, 12:48 Error Handling Python vs Rust

Situação Python Rust

Erro genérico em app Exception com contexto anyhow::Result

Bug/invariante quebrada assert , exception, crash panic! , expect

39) Regra prática definitiva


Para começar bem em Rust:
use Option para ausência normal
use Result para falha real
use match para entender
use ? para escrever código idiomático
evite unwrap() em produção
para app: considere anyhow
para biblioteca: considere thiserror
adicione contexto sempre que o erro atravessar camadas

40) Exemplo final comparativo: fluxo profissional


Python

Python Executar

def carregar_limite(path: str) -> int:


try:
with open(path, "r", encoding="utf-8") as f:
conteudo = [Link]().strip()
except OSError as e:
raise RuntimeError(f"falha ao ler arquivo {path}") from e

try:
limite = int(conteudo)
except ValueError as e:
raise ValueError(f"conteúdo inválido em {path}: {conteudo}") from e

if limite <= 0:
raise ValueError("limite deve ser positivo")

return limite

[Link] 36/38
11/03/2026, 12:48 Error Handling Python vs Rust

Rust com anyhow

Rust

use anyhow::{Context, Result};


use std::fs;

fn carregar_limite(path: &str) -> Result<i32> {


let conteudo = fs::read_to_string(path)
.with_context(|| format!("falha ao ler arquivo '{}'", path))?;

let limite = conteudo


.trim()
.parse::<i32>()
.with_context(|| format!("conteúdo inválido em '{}': '{}'", path, conteud

if limite <= 0 {
anyhow::bail!("limite deve ser positivo");
}

Ok(limite)
}

 

Conclusão
A melhor forma de resumir é esta:

Python trata erro como algo que “acontece durante a execução”.


Rust trata erro como algo que “faz parte do contrato do código”.

Esse detalhe muda tudo.

Você deixa de pensar apenas em try/except e passa a pensar em:

modelagem
tipagem
propagação explícita
recuperação controlada
contexto rico

E isso torna o software muito mais previsível.

[Link] 37/38
11/03/2026, 12:48 Error Handling Python vs Rust

Posso seguir com uma continuação prática e montar para você um mini projeto real em
Rust mostrando error handling profissional em:
leitura de arquivo
parse de JSON
variáveis de ambiente
HTTP/API
CLI com argumentos
e paralelo completo com Python módulo a módulo.

[Link] 38/38

Você também pode gostar