Pyrefly: Type Checker da Meta para Python

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.

21 Jun 2026 11 min de leitura Equipe Python Dev BR

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 Dev BR

Contribuidor do Python Dev BR

Artigos relacionados