---
title: "Pyrefly: Type Checker da Meta para Python | Python Brasil"
url: "https://python.dev.br/blog/pyrefly-type-checker-meta-python/"
markdown_url: "https://python.dev.br/blog/pyrefly-type-checker-meta-python.MD"
description: "Conheça o Pyrefly, o type checker Python da Meta escrito em Rust. Aprenda a instalar, configurar e comparar com mypy, Pyright e ty em projetos reais."
date: "2026-06-21"
author: "Equipe Python Brasil"
---

# Pyrefly: Type Checker da Meta para Python | Python Brasil

Conheça o Pyrefly, o type checker Python da Meta escrito em Rust. Aprenda a instalar, configurar e comparar com mypy, Pyright e ty em projetos reais.


Se você já tentou adicionar tipagem estática em um projeto Python de médio ou grande porte, provavelmente esbarrou na mesma pareja: o **mypy** é rigoroso, mas lento em codebases grandes; o **Pyright** (da Microsoft, base do Pylance) é rápido, mas opinionado e atrelado ao ecossistema VS Code. Em 2025, a **Meta** open-sourced uma alternativa que promete juntar o melhor dos dois mundos: o **Pyrefly**, um type checker Python escrito em <a href="https://rustlang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'rustlang.com.br' })">Rust</a>.

Neste artigo, vamos explorar o Pyrefly em profundidade: o que ele é, como instalar, como configurar em projetos reais, onde ele brilha em relação aos concorrentes e quando faz sentido adotá-lo. Se você já acompanhou nosso artigo sobre o [ty, o type checker da Astral](/blog/ty-type-checker-python-rust/), vai notar que o Pyrefly é o outro jogador importante nessa nova geração de ferramentas de tipagem para Python.

## O que é o Pyrefly?

O **Pyrefly** é um type checker para Python desenvolvido pela Meta (antiga Facebook) e usado internamente em codebases gigantescas — incluindo o próprio Instagram, que roda uma das maiores aplicações Django do mundo. Em agosto de 2025, a Meta liberou o código sob licença MIT, tornando-o disponível para a comunidade.

A motivação oficial é direta: em escala, type checkers tradicionais se tornam um gargalo. Projetos com milhões de linhas de código não podem esperar minutos por uma checagem de tipos a cada commit. O Pyrefly foi construído do zero em Rust para entregar feedback em tempo real, mesmo em repositórios enormes, sem sacrificar a profundidade da análise.

### Características principais

- **Escrito em Rust**: performance comparável ao Pyright, muito acima do mypy puro.
- **Mode de checagem configurável**: do "permissivo" (para adoção gradual) ao "estrito".
- **Language Server embutido**: funciona como LSP, integrando-se a qualquer editor moderno.
- **Compatível com PEP 484**: lê as anotações de tipo padrão do Python.
- **Suporte a features modernas**: generics via `TypeVar` (PEP 695), `Protocol`, `TypedDict`, sobrecargas, literais e mais.
- **CLI e servidor**: roda em pipeline de CI ou como servidor persistente para o editor.

O Pyrefly não é um formatador nem um linter de estilo — para isso a Meta recomenda combinar com o [Ruff](/blog/ruff-linter-formatador-python/), que cobre linting e formatação numa ferramenta só.

## Instalação do Pyrefly

A forma mais simples de instalar em 2026 é via [uv](/blog/uv-gerenciador-pacotes-python/), que gerencia a ferramenta de forma isolada do seu ambiente:

```bash
# Com uv (recomendado)
uv tool install pyrefly

# Com pip
pip install pyrefly

# Com pipx
pipx install pyrefly

# Via npm (distribuição oficial da Meta)
npm install --global @pyrefly/pyrefly
```

Verifique a instalação:

```bash
pyrefly --version
# pyrefly 0.x.x
```

Se você ainda não usa o uv, vale a pena migrar — ele tornou-se o [gerenciador de pacotes](/blog/gerenciadores-de-pacotes-python/) padrão da comunidade em 2026 e integra naturalmente com Ruff, Pyrefly e [mypy](/blog/tipagem-estatica-python-mypy/).

## Primeiros passos: checando um projeto

Para checar um projeto inteiro, basta apontar o Pyrefly para o diretório raiz:

```bash
pyrefly check .
```

Por padrão, o Pyrefly procura arquivos `.py` no caminho informado e reporta erros de tipo. Vamos criar um exemplo com alguns problemas comuns:

```python
# exemplo.py
from typing import Optional


def saudar(nome: str) -> str:
    return f"Olá, {nome}"


def processar(lista: list[int]) -> int:
    return sum(lista)


def buscar(indice: int, itens: list[str]) -> Optional[str]:
    if 0 <= indice < len(itens):
        return itens[indice]
    return None


# Erro de tipo: passando int onde se espera str
mensagem = saudar(42)

# Erro de tipo: lista com tipos misturados
processar([1, 2, "três"])

# Ok: chamada válida
resultado = buscar(0, ["a", "b"])
print(resultado.upper())  # Possível erro: resultado pode ser None
```

Rodando o Pyrefly:

```bash
pyrefly check exemplo.py
```

Saída típica:

```
exemplo.py:17:15: error: expected `str`, got `int`
exemplo.py:20:13: error: expected `int`, got `str`
exemplo.py:25:18: error: possibly-undefined attribute `upper`
```

O último erro é particularmente útil: o Pyrefly entende que `buscar` pode retornar `None` e alerta sobre o acesso a `.upper()` sem verificação prévia. Esse tipo de análise é exatamente onde tipagem estática previne bugs em produção.

## Configuração no pyproject.toml

O Pyrefly centraliza a configuração em um bloco `[tool.pyrefly]` no `pyproject.toml`, seguindo o padrão moderno do ecossistema Python:

```toml
[tool.pyrefly]
# Nível de rigor padrão do projeto
# options: "warn", "error", "strict"
project-mode = "strict"

# Caminhos a incluir na análise
include = ["src", "tests"]

# Caminhos a ignorar
exclude = [
    "src/legacy",
    "src/migrations",
    ".venv",
    "build",
]

# Versão do Python alvo
python-version = "3.12"
```

Para casos em que você quer afrouxar a checagem em arquivos específicos (por exemplo, código legado em migração), é possível usar comentários `# pyrefly: ignore` no nível do arquivo ou marcar blocos:

```python
# pyrefly: ignore  # desliga a checagem para todo o arquivo


def codigo_legado(dados):
    return dados.processar()
```

Ou inline, para suprimir um erro específico:

```python
valor = algo_ruido()  # type: ignore[possibly-undefined]
```

## Adoção gradual: o grande trunfo do Pyrefly

O diferencial mais comentado do Pyrefly em relação a ferramentas mais antigas é o **modelo de adoção gradual**. Em projetos enormes (como os da própria Meta), não é viável exigir 100% de tipagem do dia para a noite.

O Pyrefly oferece três modos principais:

1. **`warn`**: reporta apenas os erros mais óbvios, como atributos indefinidos. Ideal para começar.
2. **`error`** (padrão): reporta violações de tipo em código já anotado, mas não obriga anotação em todo lugar.
3. **`strict`**: exige anotações em todas as funções e aplica regras rígidas (equivalente ao `--strict` do mypy).

Você pode definir o modo padrão no `pyproject.toml` e sobrescrever por diretório:

```toml
[tool.pyrefly]
project-mode = "warn"

[[tool.pyrefly.overrides]]
path = "src/core"
mode = "strict"

[[tool.pyrefly.overrides]]
path = "src/experimental"
mode = "warn"
```

Essa flexibilidade permite migrar módulos críticos primeiro e deixar código experimental ou legado em modo permissivo, sem poluir o CI com centenas de erros de uma vez.

## Language Server: integração com editores

Além da CLI, o Pyrefly funciona como **Language Server** (LSP), o que significa integração em tempo real com a maioria dos editores modernos: VS Code, Neovim, Helix, Zed, Emacs e outros.

### VS Code

Instale a extensão **Pyrefly** (publicada pela Meta) e configure no `settings.json`:

```json
{
    "python.languageServer": "Pyrefly",
    "pyrefly.importStrategy": "fromEnvironment",
    "pyrefly.warnUnsupported": true
}
```

### Neovim (com lspconfig)

Se você usa [Neovim](/ferramentas/melhores-ides-editores-python/) com `nvim-lspconfig`:

```lua
require('lspconfig').pyrefly.setup({})
```

### Outros editores

Como o Pyrefly implementa o protocolo LSP, qualquer editor compatível consegue usá-lo. A vantagem em relação ao mypy é a velocidade: o feedback ao digitar é quase instantâneo, mesmo em arquivos com milhares de linhas.

## Comparação: Pyrefly vs mypy vs Pyright vs ty

A pergunta inevitável: qual type checker escolher? A resposta curta é "depende do contexto", mas a tabela abaixo ajuda a situar cada ferramenta:

| Característica       | mypy         | Pyright      | ty           | Pyrefly      |
|---------------------|--------------|--------------|--------------|--------------|
| Linguagem           | Python       | TypeScript   | Rust         | Rust         |
| Mantenedor          | Dropbox/comm.| Microsoft    | Astral       | Meta         |
| Velocidade          | Lento        | Rápido       | Muito rápido | Muito rápido |
| LSP embutido        | Não          | Sim (Pylance)| Sim          | Sim          |
| Adoção gradual      | Limitada     | Boa          | Boa          | Excelente    |
| Modo estrito        | Sim          | Sim          | Sim          | Sim          |
| Licença             | MIT          | MIT          | MIT          | MIT          |
| Maturidade          | Alta         | Alta         | Inicial      | Alta (interno)|

### Quando escolher Pyrefly

O Pyrefly faz mais sentido quando:

- Sua codebase é **grande** (centenas de milhares de linhas ou mais) e o mypy está lento demais.
- Você precisa de **adoção gradual** real, com modos configuráveis por diretório.
- O time já usa VS Code, Neovim ou outro editor com suporte LSP e quer feedback instantâneo.
- Há tolerância a uma ferramenta relativamente nova no open source, mesmo que madura internamente.

### Quando NÃO escolher Pyrefly

Pense duas vezes se:

- O projeto é pequeno e o [mypy](/blog/tipagem-estatica-python-mypy/) já atende bem — não há pressão por performance.
- Você precisa de regras muito específicas do mypy que ainda não têm equivalente no Pyrefly.
- A equipe já está deepmente integrada ao ecossistema Astral (Ruff, uv, ty) e prefere consistência.

## Exemplo prático: validando tipos em uma API FastAPI

Vamos ver o Pyrefly em ação validando uma pequena API com [FastAPI](/blog/apis-rest-com-fastapi/). Crie os arquivos:

```python
# app/models.py
from pydantic import BaseModel


class Usuario(BaseModel):
    id: int
    nome: str
    email: str
    ativo: bool = True


class CriarUsuario(BaseModel):
    nome: str
    email: str
```

```python
# app/repo.py
from typing import Optional

from app.models import Usuario, CriarUsuario


_usuarios: dict[int, Usuario] = {}
_proximo_id: int = 1


def criar(dados: CriarUsuario) -> Usuario:
    global _proximo_id
    usuario = Usuario(id=_proximo_id, **dados.model_dump())
    _usuarios[usuario.id] = usuario
    _proximo_id += 1
    return usuario


def buscar(usuario_id: int) -> Optional[Usuario]:
    return _usuarios.get(usuario_id)


def listar_ativos() -> list[Usuario]:
    return [u for u in _usuarios.values() if u.ativo]
```

```python
# app/api.py
from fastapi import FastAPI, HTTPException

from app.models import CriarUsuario, Usuario
from app.repo import criar, buscar, listar_ativos

app = FastAPI()


@app.post("/usuarios", response_model=Usuario)
def endpoint_criar(dados: CriarUsuario) -> Usuario:
    return criar(dados)


@app.get("/usuarios/{usuario_id}", response_model=Usuario)
def endpoint_buscar(usuario_id: int) -> Usuario:
    usuario = buscar(usuario_id)
    if usuario is None:
        raise HTTPException(status_code=404, detail="Usuário não encontrado")
    return usuario


@app.get("/usuarios", response_model=list[Usuario])
def endpoint_listar() -> list[Usuario]:
    return listar_ativos()
```

Agora rode o Pyrefly em modo estrito:

```bash
pyrefly check app/
```

Se houver, por exemplo, uma função que esqueça de tratar o `Optional[Usuario]`, o Pyrefly vai apontar antes mesmo de você rodar a aplicação. Isso é especialmente útil em APIs que usam [Pydantic](/blog/pydantic-validacao-dados-python/) e FastAPI, onde o fluxo de dados entre camadas é sensível a tipos.

## Integrando com pre-commit e CI

Para garantir que todo commit passe pela checagem de tipos, adicione o Pyrefly ao `.pre-commit-config.yaml`:

```yaml
repos:
  - repo: local
    hooks:
      - id: pyrefly
        name: pyrefly
        entry: pyrefly check
        language: system
        types: [python]
        pass_filenames: false
```

No GitHub Actions:

```yaml
name: CI

on: [push, pull_request]

jobs:
  typecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: astral-sh/setup-uv@v4
      - run: uv sync
      - run: uv run pyrefly check .
```

Como o Pyrefly é rápido, o impacto no tempo de pipeline é mínimo — mesmo em projetos grandes, a checagem costuma levar poucos segundos.

## Pyrefly e features modernas do Python

O Pyrefly acompanha as novidades da linguagem. Em 2026, com o [Python 3.14](/blog/python-3-14-novidades-recursos/) consolidado e o [Python 3.15](/blog/python-3-15-lazy-imports/) em desenvolvimento, recursos avançados de tipagem já são suportados:

### Generics com PEP 695 (Python 3.12+)

```python
def primeiro[T](itens: list[T]) -> T | None:
    return itens[0] if itens else None


class Pilha[T]:
    def __init__(self) -> None:
        self._dados: list[T] = []

    def empilhar(self, item: T) -> None:
        self._dados.append(item)

    def desempilhar(self) -> T | None:
        return self._dados.pop() if self._dados else None
```

### Protocols (tipagem estrutural)

Se você quer entender tipagem estrutural em profundidade, confira nosso artigo sobre [Protocols em Python](/blog/python-protocols-tipagem-estrutural/). Exemplo rápido:

```python
from typing import Protocol


class Closeable(Protocol):
    def close(self) -> None: ...


def fechar_todos(recursos: list[Closeable]) -> None:
    for r in recursos:
        r.close()


class Arquivo:
    def close(self) -> None:
        print("arquivo fechado")


# Arquivo não herda de Closeable, mas tem o método close()
fechar_todos([Arquivo()])
```

O Pyrefly valida que `Arquivo` satisfaz o protocolo `Closeable` estruturalmente, sem exigir herança explícita.

### TypedDict

```python
from typing import TypedDict


class ConfigBanco(TypedDict):
    host: str
    porta: int
    senha: str


def conectar(config: ConfigBanco) -> None:
    print(f"Conectando a {config['host']}:{config['porta']}")


# Erro: falta o campo 'senha'
conectar({"host": "localhost", "porta": 5432})
```

## Perguntas Frequentes

### O Pyrefly substitui o mypy?

Depende. Para muitos projetos novos ou em modernização, sim — especialmente se velocidade e adoção gradual forem prioridade. Para projetos que dependem de plugins específicos do mypy (como `django-stubs` em configurações muito customizadas), vale validar a compatibilidade antes de migrar.

### O Pyrefly é estável o suficiente para produção?

Sim. A Meta usa o Pyrefly há anos internamente em codebases críticas. A versão open source é a mesma base, então a maturidade do motor é alta, mesmo sendo "nova" para a comunidade externa.

### Posso usar Pyrefly junto com o Ruff?

Pode e deve. O Ruff cobre linting de estilo e formatação; o Pyrefly cobre checagem de tipos. São complementares, assim como Black + mypy eram no passado. Veja nosso guia de [configuração de linters](/guias/configurando-linters-python/) para integrar ambos.

### Como o Pyrefly se compara ao ty?

Ambos são type checkers em Rust, mas têm origens diferentes: o `ty` vem da Astral (mesma empresa do uv e Ruff) e é mais jovem; o Pyrefly vem da Meta e é mais maduro em escala. Em performance, os dois são competitivos. A escolha costuma se resumir a ecossistema preferido (Astral vs Meta) e detalhes de ergonomia. Comparar lado a lado em um projeto real é a melhor forma de decidir.

### O Pyrefly funciona com Python 2?

Não. O Pyrefly foca exclusivamente em Python 3.6+. Se você ainda mantém código Python 2, a recomendação é planejar a migração — o Python 2 está sem suporte oficial desde 2020 e representa risco de segurança.

## Conclusão

O **Pyrefly** chega para preencher uma lacuna real do ecossistema Python: um type checker rápido, moderno e pensado para adoção gradual em larga escala. Vindo da Meta, com licença MIT e implementação em Rust, ele se posiciona como alternativa séria ao mypy e ao Pyright, especialmente para times que sofrem com lentidão em codebases grandes.

A recomendação prática para 2026 é: experimente o Pyrefly se o seu projeto já passou da fase de protótipo e a tipagem estática está virando gargalo. Combine com [Ruff](/blog/ruff-linter-formatador-python/) para linting e [uv](/blog/uv-gerenciador-pacotes-python/) para gerenciamento de pacotes, e você terá um toolchain Python moderno, rápido e confiável.

Se você quer acompanhar o estado da arte em tipagem e ferramentas, vale conferir também nosso artigo sobre o [ty, o type checker da Astral](/blog/ty-type-checker-python-rust/), e nosso guia de [tipagem estática com mypy](/blog/tipagem-estatica-python-mypy/). O mercado de type checkers Python nunca esteve tão competitivo — e a comunidade só tem a ganhar.

O Pyrefly, assim como o ty e o Ruff, é escrito em <a href="https://rustlang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'rustlang.com.br' })">Rust</a> — linguagem que sustenta a nova geração de ferramentas Python de alta performance. Conhecer Rust ajuda a entender por que essas ferramentas são tão rápidas e abre portas para contribuir com o ecossistema.

Está buscando [vagas Python](/vagas/) que valorizam boas práticas e tipagem estática? Confira as oportunidades em [empresas que usam Python](/empresas/) no Brasil e destaque-se com um toolchain moderno no portfólio.
