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.

11 min de leitura Equipe Python Brasil

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 Rust.

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, 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, que cobre linting e formatação numa ferramenta só.

Instalação do Pyrefly

A forma mais simples de instalar em 2026 é via uv, que gerencia a ferramenta de forma isolada do seu ambiente:

# 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:

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 padrão da comunidade em 2026 e integra naturalmente com Ruff, Pyrefly e mypy.

Primeiros passos: checando um projeto

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

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:

# 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:

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:

[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:

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


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

Ou inline, para suprimir um erro específico:

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:

[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:

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

Neovim (com lspconfig)

Se você usa Neovim com nvim-lspconfig:

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ísticamypyPyrighttyPyrefly
LinguagemPythonTypeScriptRustRust
MantenedorDropbox/comm.MicrosoftAstralMeta
VelocidadeLentoRápidoMuito rápidoMuito rápido
LSP embutidoNãoSim (Pylance)SimSim
Adoção gradualLimitadaBoaBoaExcelente
Modo estritoSimSimSimSim
LicençaMITMITMITMIT
MaturidadeAltaAltaInicialAlta (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 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. Crie os arquivos:

# 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
# 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]
# 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:

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 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:

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

No GitHub Actions:

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 consolidado e o Python 3.15 em desenvolvimento, recursos avançados de tipagem já são suportados:

Generics com PEP 695 (Python 3.12+)

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. Exemplo rápido:

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

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 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 para linting e uv 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, e nosso guia de tipagem estática com 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 Rust — 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 que valorizam boas práticas e tipagem estática? Confira as oportunidades em empresas que usam Python no Brasil e destaque-se com um toolchain moderno no portfólio.

E

Equipe Python Brasil

Contribuidor do Python Brasil — Aprenda Python em Português