Ruff: Linter e Formatador Mais Rápido para Python | Python Brasil
Conheça o Ruff, o linter e formatador Python escrito em Rust. Aprenda a configurar, usar e substituir flake8, black e isort em um só comando.
Se você trabalha com Python profissionalmente, já deve ter configurado uma combinação de flake8, black, isort e talvez pylint nos seus projetos. Cada ferramenta tem seu arquivo de configuração, suas dependências e seu tempo de execução. E se eu te dissesse que existe uma única ferramenta que substitui todas elas e roda 10 a 100 vezes mais rápido?
Essa ferramenta é o Ruff — um linter e formatador Python escrito em Rust que está revolucionando o ecossistema de qualidade de código Python. Neste artigo, vamos explorar tudo sobre o Ruff: instalação, configuração, migração e exemplos práticos.
O que é o Ruff?
O Ruff é um linter e formatador de código Python extremamente rápido, criado por Charlie Marsh e mantido pela Astral (a mesma empresa por trás do uv). Ele é escrito em Rust, o que explica sua velocidade impressionante.
Por que o Ruff é tão popular?
- Velocidade absurda: processa milhares de arquivos em milissegundos
- Tudo em um: substitui flake8, black, isort, pylint, pyupgrade e mais
- 700+ regras incluídas, compatíveis com plugins populares do flake8
- Auto-fix: corrige automaticamente a maioria dos problemas encontrados
- Configuração unificada: tudo no
pyproject.toml - Drop-in replacement: migração quase transparente de projetos existentes
Instalação do Ruff
Existem várias formas de instalar o Ruff. A mais recomendada em 2026 é usando o uv:
# Com uv (recomendado)
uv tool install ruff
# Com pip
pip install ruff
# Com pipx
pipx install ruff
# No macOS com Homebrew
brew install ruff
Verifique a instalação:
ruff --version
# ruff 0.9.x
Usando o Ruff como Linter
O uso mais básico do Ruff é como linter. Basta apontar para um arquivo ou diretório:
# Verificar um arquivo
ruff check main.py
# Verificar todo o projeto
ruff check .
# Verificar e corrigir automaticamente
ruff check --fix .
Exemplo prático
Vamos criar um arquivo Python com alguns problemas comuns:
# exemplo.py
import os
import sys
import json
from typing import List, Dict
def calcular_media(numeros: List[int]) -> float:
soma = 0
for n in numeros:
soma += n
media = soma / len(numeros)
return media
def processar_dados(dados: Dict[str, any]):
resultado = dict()
for chave in dados.keys():
if type(dados[chave]) == str:
resultado[chave] = dados[chave].strip()
elif type(dados[chave]) == int:
resultado[chave] = dados[chave] * 2
return resultado
x = lambda a, b: a + b
nome = "Python"
print(f"Olá, {nome}!")
Rodando ruff check exemplo.py, o Ruff identifica:
exemplo.py:1:8: F401 [*] `os` imported but unused
exemplo.py:2:8: F401 [*] `sys` imported but unused
exemplo.py:3:8: F401 [*] `json` imported but unused
exemplo.py:4:21: UP006 Use `list` instead of `List` for type annotation
exemplo.py:4:28: UP006 Use `dict` instead of `Dict` for type annotation
exemplo.py:15:17: C408 Unnecessary `dict` call (rewrite as a literal)
exemplo.py:16:9: SIM118 Use `key in dict` instead of `key in dict.keys()`
exemplo.py:17:12: E721 Do not compare types, use `isinstance()`
exemplo.py:19:14: E721 Do not compare types, use `isinstance()`
exemplo.py:22:5: E731 Do not assign a `lambda` expression, use a `def`
Com ruff check --fix exemplo.py, o Ruff corrige automaticamente a maioria desses problemas:
# exemplo.py (após ruff check --fix)
from typing import Dict
def calcular_media(numeros: list[int]) -> float:
soma = 0
for n in numeros:
soma += n
media = soma / len(numeros)
return media
def processar_dados(dados: dict[str, any]):
resultado = {}
for chave in dados:
if isinstance(dados[chave], str):
resultado[chave] = dados[chave].strip()
elif isinstance(dados[chave], int):
resultado[chave] = dados[chave] * 2
return resultado
def x(a, b): return a + b
nome = "Python"
print(f"Olá, {nome}!")
Observe como o Ruff removeu imports não usados, modernizou as type annotations, simplificou o dict(), removeu .keys() desnecessário e converteu type() para isinstance().
Usando o Ruff como Formatador
Desde a versão 0.1.2, o Ruff também funciona como formatador de código, substituindo o Black:
# Formatar um arquivo
ruff format main.py
# Formatar todo o projeto
ruff format .
# Verificar formatação sem alterar (útil em CI)
ruff format --check .
O formatador do Ruff é compatível com o Black em mais de 99,9% dos casos, mas roda 30x mais rápido.
Configuração no pyproject.toml
A configuração do Ruff fica toda no pyproject.toml, eliminando a necessidade de múltiplos arquivos de configuração:
[tool.ruff]
# Versão mínima do Python alvo
target-version = "py312"
# Tamanho máximo da linha
line-length = 88
# Diretórios a ignorar
exclude = [
".git",
".venv",
"__pycache__",
"migrations",
]
[tool.ruff.lint]
# Regras ativadas
select = [
"E", # pycodestyle errors
"W", # pycodestyle warnings
"F", # pyflakes
"I", # isort
"N", # pep8-naming
"UP", # pyupgrade
"B", # flake8-bugbear
"SIM", # flake8-simplify
"C4", # flake8-comprehensions
"DTZ", # flake8-datetimez
"RUF", # ruff-specific rules
]
# Regras ignoradas
ignore = [
"E501", # line too long (formatador cuida disso)
]
# Permitir auto-fix para todas as regras habilitadas
fixable = ["ALL"]
[tool.ruff.lint.isort]
known-first-party = ["meu_projeto"]
[tool.ruff.format]
# Usar aspas duplas (compatível com Black)
quote-style = "double"
# Usar vírgula final
skip-magic-trailing-comma = false
Migrando de flake8 + black + isort
Se você já usa essas ferramentas, a migração é simples:
Passo 1: Remover ferramentas antigas
pip uninstall flake8 black isort pylint pyupgrade
Passo 2: Instalar o Ruff
uv tool install ruff
Passo 3: Converter configuração existente
O Ruff oferece um comando para converter configurações do flake8:
ruff check --show-settings
Passo 4: Atualizar scripts de CI/CD
Antes (múltiplas ferramentas):
# Antigo - lento e complexo
- run: |
black --check .
isort --check .
flake8 .
pylint src/
Depois (só Ruff):
# Novo - rápido e simples
- run: |
ruff check .
ruff format --check .
Integração com editores de código
VS Code
Instale a extensão oficial Ruff (charliermarsh.ruff) e adicione ao settings.json:
{
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.fixAll.ruff": "explicit",
"source.organizeImports.ruff": "explicit"
}
}
}
Se você usa o VS Code para Python, essa configuração vai transformar sua experiência de desenvolvimento.
Pre-commit
Adicione o Ruff ao seu .pre-commit-config.yaml:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.6
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
Ruff vs outras ferramentas: benchmark
Aqui está uma comparação de tempo de execução em um projeto com 1.000 arquivos Python:
| Ferramenta | Tempo | Multiplicador |
|---|---|---|
| Pylint | 45.2s | 1x |
| flake8 | 8.3s | 5.4x mais rápido |
| Ruff | 0.12s | 376x mais rápido |
Para formatação:
| Ferramenta | Tempo | Multiplicador |
|---|---|---|
| Black | 6.1s | 1x |
| Ruff format | 0.19s | 32x mais rápido |
Essa diferença é ainda mais impactante em pipelines de CI/CD e em projetos grandes como o Django ou projetos com muitos microsserviços.
Regras mais úteis do Ruff
O Ruff implementa regras de dezenas de plugins do flake8. Algumas das mais úteis:
# UP006: Use built-in types para annotations (Python 3.9+)
# Antes:
from typing import List, Dict, Optional
def func(items: List[str]) -> Dict[str, int]: ...
# Depois:
def func(items: list[str]) -> dict[str, int]: ...
# SIM110: Use any() ao invés de loop manual
# Antes:
for item in lista:
if item.ativo:
return True
return False
# Depois:
return any(item.ativo for item in lista)
# C4: Use comprehensions ao invés de map/filter
# Antes:
resultado = list(map(lambda x: x * 2, numeros))
# Depois:
resultado = [x * 2 for x in numeros]
# B006: Não use objetos mutáveis como argumento padrão
# Antes:
def func(items: list = []): # Bug!
items.append(1)
# Depois:
def func(items: list | None = None):
if items is None:
items = []
items.append(1)
Para mais detalhes sobre boas práticas Python, confira nosso guia atualizado.
Perguntas Frequentes
O Ruff substitui completamente o Pylint?
O Ruff implementa muitas regras do Pylint, mas não todas. Para a maioria dos projetos, o Ruff é suficiente. Se você precisa de análise estática mais profunda (como verificação de tipos), combine o Ruff com o mypy.
O Ruff funciona com Python 2?
Não. O Ruff foca exclusivamente em Python 3. Se você ainda mantém código Python 2, considere migrar — o Python 2 está sem suporte desde 2020.
Posso usar o Ruff junto com o Black?
Pode, mas não há necessidade. O formatador do Ruff (ruff format) é compatível com o Black e muito mais rápido. A recomendação é usar apenas o Ruff.
O Ruff é seguro para usar em produção?
Sim. O Ruff é usado em projetos como FastAPI, Pandas, Apache Airflow, SciPy e muitos outros projetos de grande porte. É uma ferramenta madura e confiável.
Como o Ruff se compara ao uv?
O Ruff e o uv são ferramentas complementares da mesma empresa (Astral). O Ruff cuida da qualidade de código (linting e formatação), enquanto o uv cuida do gerenciamento de pacotes e ambientes virtuais. Juntos, formam o toolkit Python mais moderno disponível.
Conclusão
O Ruff é, sem dúvida, a ferramenta de qualidade de código mais importante do ecossistema Python em 2026. Sua velocidade, abrangência e facilidade de uso tornam difícil justificar continuar usando múltiplas ferramentas separadas.
Se você está começando um projeto novo ou quer modernizar um existente, o Ruff deveria ser sua primeira escolha. Combine com o uv para gerenciamento de pacotes e você terá um workflow Python moderno, rápido e eficiente.
Está buscando vagas Python que valorizam boas práticas? Confira as oportunidades em empresas que usam Python no Brasil.
Equipe Python Brasil
Contribuidor do Python Brasil — Aprenda Python em Português