---
title: "PyO3: Integrando Rust e Python para Performance"
url: "https://python.dev.br/blog/pyo3-rust-python-alta-performance/"
markdown_url: "https://python.dev.br/blog/pyo3-rust-python-alta-performance.MD"
description: "Aprenda a usar PyO3 e maturin para criar extensões Python em Rust. Tutorial completo com exemplos práticos, benchmarks e casos de uso como Polars e Ruff."
date: "2026-04-29"
author: "Equipe python.dev.br"
---

# PyO3: Integrando Rust e Python para Performance

Aprenda a usar PyO3 e maturin para criar extensões Python em Rust. Tutorial completo com exemplos práticos, benchmarks e casos de uso como Polars e Ruff.


Se existe uma combinação que tem revolucionado o ecossistema Python nos últimos anos, é **Python + Rust**. Ferramentas que você provavelmente já usa — como [Ruff](/blog/ruff-linter-formatador-python/), [Polars](/blog/polars-alternativa-pandas-python/), [Pydantic v2](/blog/pydantic-validacao-dados-python/) e o [ty type checker](/blog/ty-type-checker-python-rust/) — são escritas em Rust e expostas para Python através do **PyO3**.

O PyO3 é um framework que permite escrever módulos nativos para Python usando Rust, com uma ergonomia surpreendente. Neste artigo, você vai aprender a configurar um projeto PyO3, criar funções e classes acessíveis pelo Python e entender por que essa abordagem supera alternativas tradicionais como ctypes e cffi.

## Por que usar Rust a partir do Python?

Python é excelente para produtividade, mas seus gargalos de performance são conhecidos. Quando o [multiprocessing](/blog/python-multiprocessing/) não resolve ou o código precisa de controle fino sobre memória, as extensões nativas entram em cena.

Rust oferece vantagens únicas para esse cenário:

- **Performance previsível** — sem garbage collector, sem overhead de runtime
- **Segurança de memória** — o compilador previne data races e acessos inválidos em tempo de compilação
- **Binários pequenos** — extensões Rust são compactas e não exigem runtime adicional
- **Ecossistema maduro** — crates para parsing, criptografia, compressão e muito mais

Comparado com C/C++ via ctypes ou cffi, o PyO3 oferece uma experiência muito mais segura e ergonômica, com conversão automática de tipos entre Rust e Python.

## Configurando o ambiente

Você precisa de Rust (via rustup) e do **maturin**, a ferramenta de build para projetos PyO3. Recomendamos usar o [uv](/blog/uv-gerenciador-pacotes-python/) para gerenciar o ambiente Python:

```bash
# Instalar Rust (se ainda não tem)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

# Criar ambiente virtual e instalar maturin
uv venv .venv
source .venv/bin/activate
uv pip install maturin
```

Agora crie um novo projeto PyO3:

```bash
# Criar projeto com template pyo3
maturin init --bindings pyo3

# Estrutura gerada:
# ├── Cargo.toml
# ├── pyproject.toml
# └── src/
#     └── lib.rs
```

## Estrutura do Cargo.toml

O `Cargo.toml` gerado já vem configurado para PyO3:

```toml
[package]
name = "meu_modulo"
version = "0.1.0"
edition = "2021"

[lib]
name = "meu_modulo"
crate-type = ["cdylib"]

[dependencies]
pyo3 = { version = "0.23", features = ["extension-module"] }
```

O `crate-type = ["cdylib"]` indica que o Rust vai gerar uma biblioteca dinâmica compatível com Python. A feature `extension-module` garante que o módulo funcione corretamente quando importado.

## Criando funções Python em Rust

Vamos criar uma função que calcula a soma de quadrados de uma lista — um exemplo simples que demonstra a diferença de performance:

```rust
use pyo3::prelude::*;

/// Calcula a soma dos quadrados de um vetor de inteiros.
#[pyfunction]
fn soma_quadrados(numeros: Vec<i64>) -> i64 {
    numeros.iter().map(|n| n * n).sum()
}

/// Módulo Python gerado pelo PyO3.
#[pymodule]
fn meu_modulo(m: &Bound<'_, PyModule>) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(soma_quadrados, m)?)?;
    Ok(())
}
```

O macro `#[pyfunction]` transforma uma função Rust comum em uma função chamável pelo Python. O `#[pymodule]` define o ponto de entrada do módulo.

## Compilando e testando

Com o maturin, a compilação e instalação são feitas em um único comando:

```bash
# Compilar e instalar no ambiente virtual ativo
maturin develop --release
```

Agora você pode usar o módulo diretamente no Python:

```python
import meu_modulo

resultado = meu_modulo.soma_quadrados([1, 2, 3, 4, 5])
print(resultado)  # 55
```

## Criando classes com #[pyclass]

O PyO3 também permite expor structs Rust como classes Python:

```rust
use pyo3::prelude::*;

#[pyclass]
struct Contador {
    valor: i64,
}

#[pymethods]
impl Contador {
    #[new]
    fn new(inicio: i64) -> Self {
        Contador { valor: inicio }
    }

    fn incrementar(&mut self, n: i64) {
        self.valor += n;
    }

    fn obter(&self) -> i64 {
        self.valor
    }
}

#[pymodule]
fn meu_modulo(m: &Bound<'_, PyModule>) -> PyResult<()> {
    m.add_class::<Contador>()?;
    Ok(())
}
```

No Python, a classe funciona naturalmente:

```python
from meu_modulo import Contador

c = Contador(0)
c.incrementar(10)
print(c.obter())  # 10
```

## Benchmark: Rust vs Python puro

Vamos comparar a função `soma_quadrados` em ambas as linguagens com uma lista de 10 milhões de elementos:

```python
import time

def soma_quadrados_py(numeros):
    return sum(n * n for n in numeros)

dados = list(range(10_000_000))

# Python puro
inicio = time.perf_counter()
soma_quadrados_py(dados)
tempo_py = time.perf_counter() - inicio

# Rust via PyO3
import meu_modulo

inicio = time.perf_counter()
meu_modulo.soma_quadrados(dados)
tempo_rs = time.perf_counter() - inicio

print(f"Python: {tempo_py:.3f}s")
print(f"Rust:   {tempo_rs:.3f}s")
print(f"Speedup: {tempo_py / tempo_rs:.1f}x")
```

| Implementação | Tempo (10M elementos) | Speedup |
|---|---|---|
| Python puro (generator) | ~1.8s | 1x |
| NumPy | ~0.04s | ~45x |
| Rust via PyO3 | ~0.02s | ~90x |

A extensão Rust supera até o NumPy nesse cenário, porque evita a alocação de arrays intermediários e opera diretamente sobre os dados.

## Casos de uso reais

Os projetos Python mais influentes de 2024-2026 usam PyO3:

| Projeto | O que faz | Por que usa Rust |
|---|---|---|
| [Ruff](/blog/ruff-linter-formatador-python/) | Linter e formatador | 10-100x mais rápido que Flake8 |
| [Polars](/blog/polars-alternativa-pandas-python/) | DataFrame analytics | Processamento paralelo sem GIL |
| [Pydantic v2](/blog/pydantic-validacao-dados-python/) | Validação de dados | Core de validação 5-50x mais rápido |
| [uv](/blog/uv-gerenciador-pacotes-python/) | Gerenciador de pacotes | Resolução de dependências em segundos |
| [ty](/blog/ty-type-checker-python-rust/) | Type checker | Análise de tipos ultrarrápida |

Esses projetos demonstram um padrão claro: manter a interface Pythonica enquanto o trabalho pesado roda em Rust.

## PyO3 vs ctypes vs cffi

| Característica | PyO3 | ctypes | cffi |
|---|---|---|---|
| Linguagem | Rust | C | C |
| Segurança de memória | Garantida pelo compilador | Manual | Manual |
| Conversão de tipos | Automática | Manual | Semi-automática |
| Suporte a classes | Nativo (#[pyclass]) | Limitado | Limitado |
| Async/await | Suportado | Não | Não |
| Ergonomia | Alta | Baixa | Média |

O PyO3 é a escolha mais moderna e segura para extensões nativas. Se você já usa Rust ou está disposto a aprender, a curva de aprendizado compensa rapidamente.

## Dicas para produção

1. **Use `maturin build --release`** para gerar wheels otimizadas para distribuição
2. **Aproveite o paralelismo** — Rust pode usar threads sem se preocupar com o GIL
3. **Publique no PyPI** — o maturin gera wheels compatíveis com `pip install`
4. **Comece pequeno** — identifique o gargalo com profiling antes de reescrever em Rust

Para gerenciar seus [ambientes virtuais](/blog/virtual-environments-python/) durante o desenvolvimento, o uv simplifica bastante o fluxo com PyO3.

Se você se interessa por linguagens compiladas de alta performance, vale conhecer também o ecossistema <a href="https://rustlang.com.br/blog/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', {source: 'python.dev.br', target: 'rustlang.com.br', content: 'pyo3-rust-python'})">Rust no rustlang.com.br</a>, que cobre o lado puro da linguagem. Desenvolvedores que trabalham com backends de alta concorrência podem comparar a abordagem de goroutines em <a href="https://golang.com.br/blog/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', {source: 'python.dev.br', target: 'golang.com.br', content: 'pyo3-rust-python'})">golang.com.br</a> com o modelo async do Rust. Já quem desenvolve para JVM pode explorar as extensões nativas via JNI em <a href="https://kotlin.dev.br/blog/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', {source: 'python.dev.br', target: 'kotlin.dev.br', content: 'pyo3-rust-python'})">kotlin.dev.br</a>.

## Perguntas frequentes

### O que é o PyO3?
PyO3 é um framework open source que permite escrever módulos nativos para Python usando a linguagem Rust. Ele fornece macros como `#[pyfunction]` e `#[pyclass]` que convertem automaticamente tipos entre Rust e Python.

### Preciso saber Rust para usar PyO3?
Sim, conhecimento básico de Rust é necessário. Porém, para funções simples de processamento de dados, a curva de aprendizado é acessível. Muitos desenvolvedores aprendem Rust justamente para criar extensões Python mais rápidas.

### O PyO3 substitui o Cython?
Para novos projetos, o PyO3 é geralmente uma escolha melhor que o Cython. Ele oferece segurança de memória garantida pelo compilador Rust, melhor tooling e performance comparável ou superior. Projetos existentes em Cython não precisam migrar imediatamente.

### Como distribuir um pacote PyO3 no PyPI?
O maturin gera wheels pré-compiladas para diversas plataformas. Basta rodar `maturin build --release` e fazer upload com `twine upload` ou configurar CI/CD para publicação automática. O processo é similar a publicar qualquer outro pacote Python.
