Linting e formatação
Esta aula aborda ferramentas essenciais de linting e formatação para Python: flake8, ruff, black e isort. Você aprenderá a configurá-las, integrá-las ao seu editor e ao fluxo de desenvolvimento, garantindo código limpo, consistente e de alta qualidade.
Bem-vindo à aula 71 do nosso curso de Python! Hoje vamos mergulhar em um aspecto fundamental do desenvolvimento profissional: a qualidade do código. Escrever código que funciona é apenas o começo; código legível, consistente e fácil de manter é o que diferencia um desenvolvedor amador de um profissional. Para isso, usamos ferramentas de linting e formatação.
Nesta aula, você vai conhecer as principais ferramentas do ecossistema Python: flake8 e ruff (para linting), black (para formatação) e isort (para ordenação de imports). Vamos ver como cada uma funciona, como configurá-las e como integrá-las ao seu editor de código para que seu trabalho seja mais produtivo e seu código, impecável.
flake8/ruff (visão geral)
Linting é o processo de análise estática do código para identificar problemas potenciais, como erros de sintaxe, variáveis não utilizadas, importações desnecessárias, violações de estilo e até mesmo bugs sutis. As ferramentas de linting atuam como revisores automatizados, apontando trechos que podem causar problemas ou que não seguem as convenções da comunidade.
O flake8 é uma das ferramentas mais tradicionais e amplamente utilizadas. Ele combina três utilitários: PyFlakes (para erros lógicos), pycodestyle (para estilo PEP 8) e McCabe (para complexidade ciclomática). Ele é rápido, configurável e produz relatórios claros. No entanto, sua configuração pode ser um pouco verbosa, e sua velocidade não é a mais alta.
O ruff é uma ferramenta moderna, escrita em Rust, que está ganhando enorme popularidade. Ele é extremamente rápido (muitas vezes mais de 10 vezes mais rápido que flake8), suporta centenas de regras (incluindo todas as do flake8 e muitas outras) e permite uma configuração unificada. Além disso, o ruff também pode formatar código (como o black) e ordenar imports (como o isort), sendo uma alternativa completa em um único binário.
Vamos ver um exemplo de como usar o flake8 em um projeto simples. Primeiro, instale com pip:
pip install flake8Agora, crie um arquivo exemplo.py com o seguinte conteúdo (propositalmente com problemas):
import os
import sys
def soma(a,b):
return a+b
x = 1
print(soma(x, 2))
print(os.getcwd())
Execute o flake8:
flake8 exemplo.pyA saída mostrará avisos como:
exemplo.py:1:1: F401 'os' imported but unused
exemplo.py:2:1: F401 'sys' imported but unused
exemplo.py:4:1: E302 expected 2 blank lines, found 1
exemplo.py:4:11: E231 missing whitespace after ','
exemplo.py:4:14: E231 missing whitespace after ','
Cada código (F401, E302, etc.) indica o tipo de problema. Você pode configurar o flake8 no arquivo .flake8 ou no setup.cfg (ou tox.ini). Por exemplo, para ignorar a regra E302 e definir o comprimento máximo da linha como 100:
[flake8]
max-line-length = 100
ignore = E302
Já o ruff pode ser instalado e usado de forma semelhante:
pip install ruff
ruff check exemplo.pyA saída será algo como:
exemplo.py:1:1: F401 [*] `os` imported but unused
exemplo.py:2:1: F401 [*] `sys` imported but unused
exemplo.py:4:11: E231 [*] Missing whitespace after ','
exemplo.py:4:14: E231 [*] Missing whitespace after ','
Found 4 errors.
[*] 4 potentially fixable with the --fix flag.
O ruff também pode corrigir automaticamente muitos problemas com ruff check --fix. Além disso, o ruff é altamente configurável via pyproject.toml ou um arquivo ruff.toml. Exemplo de configuração:
[tool.ruff]
line-length = 100
select = ["E", "F", "W", "I"]
ignore = ["E302"]
Ambas as ferramentas são excelentes; a escolha depende do seu projeto e preferência. O ruff é recomendado para novos projetos pela velocidade e facilidade de uso.
black
O black é um formatador de código Python que segue a filosofia de "formatação sem opções". Ele reformata seu código para conformidade com uma versão estendida do PEP 8, garantindo estilo consistente em todo o projeto. A principal vantagem é que você não precisa gastar tempo discutindo estilo: o black decide por você, e o resultado é sempre uniforme.
O black é frequentemente chamado de "o formatador implacável" porque ele reformata até mesmo código que já parece razoável, mas com pequenas diferenças. Por exemplo, ele coloca parênteses em expressões longas, ajusta aspas, espaçamentos e quebras de linha. Ele é amplamente adotado em projetos grandes como Django e Pandas.
Para instalar e usar:
pip install black
black exemplo.pyO black modificará o arquivo, reescrevendo o código. Veja um exemplo de antes e depois:
Antes:
def soma(a,b):
return a+b
Depois de rodar o black:
def soma(a, b):
return a + b
Note que o black adicionou espaços após as vírgulas, espaços ao redor do operador + e duas linhas em branco no final (padrão do black).
Você pode configurar o black via pyproject.toml. Exemplo:
[tool.black]
line-length = 100
skip-string-normalization = true
O black também pode ser usado como um pré-commit hook (veremos depois). É importante integrá-lo ao fluxo de trabalho para que todos os colaboradores usem o mesmo estilo.
Uma dica: o black pode ser usado com o flake8, mas você deve configurar o flake8 para ignorar as regras de estilo que o black gerencia (como E203, E501, etc.). O black fornece uma lista de regras para ignorar, que você pode adicionar ao seu arquivo de configuração.
isort
O isort é uma ferramenta que ordena e organiza as importações em seus arquivos Python. Uma boa organização de imports é importante para legibilidade e para evitar conflitos. O isort separa as importações em seções: padrão da biblioteca, terceiros e locais, e as ordena alfabeticamente dentro de cada seção.
Vamos ver um exemplo de código com imports desordenados:
import sys
import os
import requests
from django.db import models
from meu_projeto import utils
Rodando o isort:
pip install isort
isort exemplo.pyO resultado será:
import os
import sys
import requests
from django.db import models
from meu_projeto import utils
Note que o isort adicionou linhas em branco entre as seções e ordenou alfabeticamente os módulos dentro de cada seção.
O isort pode ser configurado no pyproject.toml ou em um arquivo .isort.cfg. Exemplo:
[tool.isort]
profile = "black"
line_length = 100
O perfil black garante compatibilidade com o black, evitando conflitos de formatação. Existem outros perfis, como django, pandas, etc.
Combinar isort com black é uma prática comum: primeiro você roda o isort para organizar os imports e depois o black para formatar o restante do código. Em pré-commit hooks, a ordem geralmente é: isort, black, flake8/ruff.
Integração com o editor
Usar essas ferramentas diretamente no terminal é útil, mas o ideal é integrá-las ao seu editor de código para que a verificação e formatação aconteçam automaticamente enquanto você digita. Isso melhora a produtividade e garante que o código esteja sempre em conformidade.
No VS Code, você pode instalar a extensão Python (da Microsoft) e configurar as seguintes opções no settings.json:
{
"python.linting.enabled": true,
"python.linting.flake8Enabled": true,
"python.linting.lintOnSave": true,
"python.formatting.provider": "black",
"python.formatting.blackArgs": ["--line-length", "100"],
"python.sortImports.args": ["--profile", "black"],
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
}
Isso habilitará o flake8 para linting, o black como formatador e o isort para organizar imports ao salvar. Você também pode usar o ruff no lugar do flake8, instalando a extensão ruff e ajustando as configurações.
No PyCharm, você pode configurar ferramentas externas: vá em Settings > Tools > External Tools e adicione entradas para black e isort. Para linting, você pode habilitar o flake8 ou ruff como inspetor (Settings > Editor > Inspections > Python > Flake8).
Além disso, uma prática recomendada é usar pre-commit hooks para executar essas ferramentas em um estágio de commit. Crie um arquivo .pre-commit-config.yaml na raiz do projeto:
repos:
- repo: https://github.com/psf/black
rev: 23.12.1
hooks:
- id: black
language_version: python3.11
- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
- id: isort
args: ["--profile", "black"]
- repo: https://github.com/PyCQA/flake8
rev: 6.1.0
hooks:
- id: flake8
Depois, instale os hooks com pre-commit install. Assim, antes de cada commit, o código é verificado e corrigido automaticamente, se necessário.
Boas práticas e observações finais
Ao adotar essas ferramentas, lembre-se de que elas são aliadas, não inimigas. No início, pode parecer que estão sendo chatas com você, mas elas estão ajudando a manter um padrão profissional. Configure-as de forma que atendam às necessidades do seu time e use-as consistentemente.
Algumas dicas:
- Use o ruff se estiver começando um novo projeto: ele é mais rápido e cobre linting, formatação e ordenação de imports.
- Mantenha a configuração das ferramentas no
pyproject.tomlpara centralizar as definições. - Integre as ferramentas ao seu editor e ao pre-commit para garantir que todos do time sigam as mesmas regras.
- Não tenha medo de ajustar as regras, mas faça isso com consciência. Evite desabilitar muitas regras sem motivo.
Referências
- Documentação oficial do flake8
- Documentação oficial do Ruff
- Documentação oficial do Black
- Documentação oficial do isort
- PEP 8 - Style Guide for Python Code
- Pre-commit
- VS Code Python Linting
Exercícios
Instale o flake8 e o ruff em um ambiente virtual e execute ambos em um arquivo Python com alguns erros intencionais (por exemplo, import não utilizado, espaçamento incorreto). Compare as saídas e anote as diferenças.
✓ Resposta:Exemplo de arquivo com erros:
import os import sys def soma(a,b): return a+b print(soma(1,2))Ao rodar
flake8 exemplo.py, você verá avisos como F401 e E231. Ao rodarruff check exemplo.py, a saída será semelhante, mas com sugestão de correção (--fix). As principais diferenças são a velocidade (ruff é mais rápido) e a possibilidade de autofix.Crie um arquivo Python com imports desordenados e rode o isort com o perfil black. Explique o que aconteceu.
✓ Resposta:Exemplo de arquivo:
import sys import os import requests from django.db import models from meu_projeto import utilsRodando
isort --profile black exemplo.py, o arquivo será reorganizado para:import os import sys import requests from django.db import models from meu_projeto import utilsO isort agrupou as importações por tipo (biblioteca padrão, terceiros, local) e ordenou alfabeticamente. O perfil black ajusta o estilo para ser compatível com o black.
Configure o black para usar um comprimento de linha de 120 e rode-o em um arquivo com linhas longas. Mostre o antes e depois.
✓ Resposta:Arquivo
exemplo.py:def funcao_com_nome_muito_longo(parametro_um, parametro_dois, parametro_tres, parametro_quatro, parametro_cinco): return parametro_um + parametro_dois + parametro_tres + parametro_quatro + parametro_cincoRodando
black --line-length 120 exemplo.py, o black reformata para:def funcao_com_nome_muito_longo( parametro_um, parametro_dois, parametro_tres, parametro_quatro, parametro_cinco, ): return ( parametro_um + parametro_dois + parametro_tres + parametro_quatro + parametro_cinco )O black quebrou a linha para respeitar o limite de 120 caracteres, usando parênteses e indentação.
Integre o flake8 e o black ao VS Code (ou outro editor de sua preferência) e configure o salvamento automático para formatar e lintar. Documente os passos.
✓ Resposta:No VS Code, instale a extensão Python. Depois, adicione ao
settings.json:{ "python.linting.enabled": true, "python.linting.flake8Enabled": true, "python.formatting.provider": "black", "editor.formatOnSave": true, "python.linting.lintOnSave": true }Isso fará com que, ao salvar, o black formate o código e o flake8 aponte problemas. Você pode ver os erros na aba "Problems".
Crie um arquivo
.pre-commit-config.yamlcom black, isort e flake8 e instale os hooks. Teste com um commit.✓ Resposta:Arquivo
.pre-commit-config.yaml:repos: - repo: https://github.com/psf/black rev: 23.12.1 hooks: - id: black - repo: https://github.com/PyCQA/isort rev: 5.13.2 hooks: - id: isort args: ["--profile", "black"] - repo: https://github.com/PyCQA/flake8 rev: 6.1.0 hooks: - id: flake8Depois, execute
pre-commit install. Ao tentar fazer um commit, o pre-commit rodará as ferramentas. Se houver alterações, o commit será bloqueado até que você as corrija (ou use--no-verifypara ignorar).