Linters Python: Flake8, Black e Ruff
Configure linters e formatadores para Python. Guia completo de Flake8, Black e Ruff com exemplos, integração com editores e CI/CD
Introdução
Linters e formatadores são ferramentas que analisam seu código Python e garantem que ele siga padrões de qualidade e estilo. Eles detectam erros, inconsistências e problemas de legibilidade automaticamente, antes mesmo de rodar o código.
Neste guia, vamos configurar as três ferramentas mais populares: Flake8 (linter), Black (formatador) e Ruff (que substitui ambos com velocidade superior).
O que é o PEP 8?
O PEP 8 é o guia oficial de estilo para código Python. Ele define regras como:
- Usar 4 espaços para indentação (não tabs)
- Linhas com no máximo 79 caracteres (muitos projetos usam 88 ou 120)
- Duas linhas em branco antes de funções e classes de nível superior
- Espaços ao redor de operadores:
x = 1 + 2em vez dex=1+2 - Importações organizadas por tipo (stdlib, terceiros, locais)
Seguir o PEP 8 torna o código mais legível e consistente, especialmente em equipes.
Flake8: o linter clássico
O Flake8 verifica se o código segue o PEP 8 e detecta erros comuns:
pip install flake8
Usando o Flake8
# Verificar um arquivo
flake8 app.py
# Verificar todo o projeto
flake8 src/
# Verificar com estatisticas
flake8 --statistics src/
Exemplo de saída:
app.py:5:1: E302 expected 2 blank lines, found 1
app.py:10:80: E501 line too long (95 > 79 characters)
app.py:15:1: F401 'os' imported but unused
Cada mensagem indica o arquivo, linha, coluna e o código do erro.
Configurando o Flake8
Crie um arquivo .flake8 na raiz do projeto:
[flake8]
max-line-length = 88
exclude =
venv,
.git,
__pycache__,
build,
dist
ignore = E203, W503
per-file-ignores =
__init__.py: F401
A configuração max-line-length = 88 é compatível com o Black. O E203 e W503 são ignorados porque conflitam com o estilo do Black.
Plugins úteis do Flake8
pip install flake8-bugbear # Detecta bugs comuns
pip install flake8-comprehensions # Otimiza list comprehensions
pip install flake8-docstrings # Verifica docstrings
Black: o formatador inflexível
O Black formata o código automaticamente seguindo um estilo consistente. Ele é “inflexível” por design — oferece poucas opções de configuração, o que elimina debates sobre estilo em equipes:
pip install black
Usando o Black
# Formatar um arquivo
black app.py
# Formatar todo o projeto
black src/
# Apenas verificar (sem alterar)
black --check src/
# Mostrar as alterações que seriam feitas
black --diff src/
Exemplo de formatação
Antes do Black:
def calcular(a,b,c,d,e,f,g,h):
resultado = a+b+c+d+e+f+g+h
return {'soma':resultado,'media':resultado/8,'valores':[a,b,c,d,e,f,g,h]}
Depois do Black:
def calcular(a, b, c, d, e, f, g, h):
resultado = a + b + c + d + e + f + g + h
return {
"soma": resultado,
"media": resultado / 8,
"valores": [a, b, c, d, e, f, g, h],
}
Configurando o Black
No pyproject.toml:
[tool.black]
line-length = 88
target-version = ['py312']
O Black intencionalmente tem poucas opções. A ideia é que todos usem o mesmo estilo.
Ruff: o substituto ultrarrápido
O Ruff é um linter e formatador escrito em Rust, 10 a 100 vezes mais rápido que Flake8 e Black combinados. Ele implementa as mesmas regras e pode substituir ambos:
pip install ruff
Usando o Ruff como linter
# Verificar o codigo
ruff check src/
# Corrigir problemas automaticamente
ruff check --fix src/
Usando o Ruff como formatador
# Formatar (substitui o Black)
ruff format src/
# Verificar formatação
ruff format --check src/
Configurando o Ruff
No pyproject.toml:
[tool.ruff]
line-length = 88
target-version = "py312"
[tool.ruff.lint]
select = [
"E", # pycodestyle errors
"F", # pyflakes
"I", # isort (organização de imports)
"N", # pep8-naming
"UP", # pyupgrade
"B", # flake8-bugbear
"SIM", # flake8-simplify
"C4", # flake8-comprehensions
]
ignore = ["E501"] # Ignorar linha longa (o formatador cuida disso)
[tool.ruff.lint.isort]
known-first-party = ["meu_pacote"]
Por que migrar para o Ruff?
O Ruff oferece várias vantagens sobre Flake8 e Black:
- Velocidade: verifica projetos grandes em milissegundos
- Tudo em um: linter, formatador e organizador de imports
- Compatível: implementa centenas de regras do Flake8 e plugins
- Configuração centralizada: tudo no
pyproject.toml - Correção automática: muitas regras podem ser corrigidas com
--fix
Organizando imports com isort
O isort organiza imports automaticamente em três grupos: stdlib, terceiros e locais:
pip install isort
Se você usa Ruff com a regra "I", o isort já está incluso e não precisa ser instalado separadamente.
Antes:
from flask import Flask
import os
from meu_pacote import utils
import sys
import requests
Depois:
import os
import sys
import requests
from flask import Flask
from meu_pacote import utils
Integração com editores
VS Code
Instale a extensão Ruff (ou Black + Flake8) e configure no settings.json:
{
"[python]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "charliermarsh.ruff"
}
}
PyCharm
O PyCharm tem inspeções embutidas, mas você pode adicionar Ruff ou Black como External Tool em Settings > Tools > External Tools.
Pre-commit hooks
Use o pre-commit para rodar linters automaticamente antes de cada commit:
pip install pre-commit
Crie .pre-commit-config.yaml:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.0
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
Instale os hooks:
pre-commit install
Agora, a cada git commit, o Ruff verifica e formata o código automaticamente.
Qual ferramenta escolher?
Para projetos novos, a recomendação é usar Ruff como ferramenta única. Ele substitui Flake8, Black e isort com melhor desempenho e configuração mais simples.
Para projetos existentes que já usam Flake8 e Black, a migração para Ruff é simples e geralmente requer apenas copiar as configurações para o pyproject.toml.
Conclusão
Linters e formatadores eliminam discussões sobre estilo de código e detectam problemas antes que eles cheguem à produção. O Ruff se destaca como a ferramenta mais moderna e eficiente, unificando funcionalidades que antes exigiam múltiplas ferramentas. Configure-os desde o início do projeto e integre com pre-commit hooks para que a verificação aconteça automaticamente em cada commit.