
Passo 1 de 8
Executar o linter e interpretar os diagnósticos
Execute o Ruff sobre um arquivo local e aprenda a relacionar cada diagnóstico ao trecho correspondente do código.
Trilha de aprendizado · Nível 8 · Tutorial 9
Interpretar diagnósticos de análise estática, corrigir problemas simples e aplicar correções automáticas de maneira criteriosa.
Executar o linter e interpretar os diagnósticos
Execute o Ruff sobre um arquivo local e aprenda a relacionar cada diagnóstico ao trecho correspondente do código. 2 min
Corrigir importações sem uso e nomes indefinidos
Decida como tratar F401 e F821 sem alterar a finalidade do código apenas para eliminar diagnósticos. 2 min
Investigar atribuições locais sem uso
Interprete o diagnóstico F841 e escolha uma correção que preserve a finalidade e os efeitos necessários da função. 2 min
Entender quais regras foram verificadas
Interprete o resultado do Ruff considerando o arquivo analisado e as regras habilitadas na execução. 1 min
Revisar e aplicar correções automáticas
Use a prévia do Ruff, revise as alterações propostas, aplique apenas correções adequadas e confirme o resultado com lint e testes. 3 min
Usar noqa apenas quando houver justificativa
Diferencie uma supressão pontual e documentada de tentativas de esconder defeitos reais. 1 min
Reconhecer o que o lint não comprova
Compare o alcance do lint, da verificação de tipos e dos testes para interpretar corretamente resultados positivos. 1 min
Aplicar o ciclo completo de análise e revisão
Conclua uma revisão local com Ruff, corrija os diagnósticos conforme a intenção do código e confirme o comportamento com pytest. 2 min

Passo 1 de 8
Execute o Ruff sobre um arquivo local e aprenda a relacionar cada diagnóstico ao trecho correspondente do código.
Você já usou o Ruff para padronizar a apresentação do código. O lint tem outro objetivo: examina o arquivo sem executar o programa e procura padrões de estilo ou indícios de possíveis problemas.
A formatação pode ajustar espaços, aspas e quebras de linha. O lint, por sua vez, produz diagnósticos que apontam onde um padrão foi encontrado. Nesta etapa, você apenas executará a análise e aprenderá a ler esses diagnósticos, sem corrigir o arquivo.
Dica
O comando ruff check usado nesta prática não modifica nem executa analise.py. Ele apenas analisa o código-fonte.
No terminal, crie uma pasta para a prática, entre nela e abra essa pasta no editor de sua preferência. Use o mesmo ambiente Python em que o Ruff já está instalado.
mkdir ruff_analise
cd ruff_analiseCrie o arquivo analise.py e salve exatamente este conteúdo:
import math
def calcular_total(preco, quantidade):
subtotal = preco * quantidade
desconto = subtotal * 0.1
return total
print(calcular_total(50, 2))Com o terminal na mesma pasta do arquivo, execute:
python -m ruff check analise.pyA aparência pode variar um pouco conforme a versão do Ruff, mas cada diagnóstico informa os mesmos elementos essenciais:
F821;Por exemplo, a localização analise.py:7:12 aponta para a linha 7, coluna 12. Nessa posição começa o nome total da instrução return total. O código e a mensagem explicam qual diagnóstico foi associado a esse ponto.

A localização conduz ao trecho do arquivo; o código identifica a regra e a mensagem descreve o que foi detectado.
Exemplo
Sua saída deve indicar três pontos do arquivo, embora o formato visual possa variar:
analise.py:1:8 — código F401;analise.py:6:5 — código F841;analise.py:7:12 — código F821.Por enquanto, não altere o arquivo. O objetivo é localizar e interpretar as informações apresentadas.
Escolha um dos diagnósticos exibidos no seu terminal. Informe o arquivo, a linha, a coluna, o código da regra e o trecho ao qual ele aponta. Se sua saída diferir do exemplo, registre o resultado que você realmente observou.
Escreva pelo menos 40 caracteres (0/40).

Passo 2 de 8
Decida como tratar F401 e F821 sem alterar a finalidade do código apenas para eliminar diagnósticos.
O diagnóstico F401 indica que uma importação não é utilizada no código analisado. Isso não determina sozinho a correção.
No exemplo, math não participa do cálculo. Se a intenção é manter a expressão atual, a importação é dispensável. Se a intenção é usar explicitamente a função de raiz quadrada da biblioteca, o retorno pode chamar math.sqrt(...).
Analise a finalidade antes de escolher entre remover a primeira linha e usar math.sqrt.
import math
def hipotenusa(cateto_a, cateto_b):
return (cateto_a**2 + cateto_b**2) ** 0.5
Dica
Não acrescente um uso artificial para justificar uma importação. A correção deve ser explicável pelo comportamento esperado do programa.
O diagnóstico F821 aponta uma referência a um nome que não está definido naquele contexto. Antes de corrigir, verifique se houve:
Atribuir qualquer valor ao nome elimina a mensagem, mas pode esconder o defeito. No exemplo, a função recebeu taxa; portanto, usar taxa no cálculo é mais coerente do que inventar um valor para desconto. De modo semelhante, se Path(...) for necessário, a correção pode ser importar Path de pathlib, e não criar um nome arbitrário chamado Path.
Comparação didática entre o trecho original e a correção orientada pelo parâmetro da função.
# Antes: "desconto" não foi definido.
def aplicar_desconto(preco, taxa):
return preco * (1 - desconto) # F821
# Depois: o cálculo usa o parâmetro recebido.
def aplicar_desconto_corrigido(preco, taxa):
return preco * (1 - taxa)

A correção reconecta a expressão a um nome que já faz parte do contrato da função, em vez de criar um valor arbitrário.
Relacione cada situação à correção mais coerente.
Toque em um item e depois no par correspondente.

Passo 3 de 8
Interprete o diagnóstico F841 e escolha uma correção que preserve a finalidade e os efeitos necessários da função.
O diagnóstico F841 aparece quando uma variável local recebe um valor, mas não é utilizada depois. Isso pode revelar um cálculo abandonado, uma atribuição desnecessária ou um resultado que deveria participar de uma operação ou do retorno.
No exemplo, o contrato da função exige o preço com desconto. O valor total é calculado, mas o retorno usa subtotal.
O Ruff aponta F841 na atribuição a total.
def calcular_preco_final(valores, desconto):
subtotal = sum(valores)
total = subtotal - desconto
return subtotal

Um cálculo necessário deve chegar ao uso previsto pelo contrato, como uma operação posterior ou o retorno.
No primeiro exemplo, apagar total apenas eliminaria o aviso e manteria o retorno incorreto. A correção coerente é return total.
Em outros casos, o valor devolvido por uma chamada pode ser dispensável, mas a própria chamada pode produzir um efeito necessário. Nesse caso, remova somente a atribuição, não a chamada inteira.
O contrato exige salvar o pedido, mas não exige usar o protocolo devolvido.
# Antes: protocolo recebe um valor que não é usado.
def registrar_envio(pedido, repositorio):
protocolo = repositorio.salvar(pedido)
return "Envio registrado"
# Depois: a gravação continua acontecendo.
def registrar_envio(pedido, repositorio):
repositorio.salvar(pedido)
return "Envio registrado"
Dica
Pergunte: esse valor deveria ser retornado ou usado depois? A expressão produz algum efeito necessário? Corrija conforme o contrato da função, em vez de apenas renomear ou apagar a variável para silenciar o diagnóstico.
Considere o contrato descrito nos comentários de cada função.
# Deve devolver a soma dos itens incluindo o frete.
def calcular_total(itens, frete):
total = sum(itens) + frete
return sum(itens)
# Deve gravar o acesso e informar que a operação terminou.
# O valor devolvido por gravar não é necessário.
def registrar_acesso(usuario, auditoria):
registro = auditoria.gravar(usuario)
return True
Para cada função, proponha uma alteração que resolva o F841. Explique também por que remover toda a instrução diagnosticada seria adequado ou inadequado.
Escreva pelo menos 80 caracteres (0/80).

Passo 4 de 8
Interprete o resultado do Ruff considerando o arquivo analisado e as regras habilitadas na execução.
O Ruff possui um catálogo amplo de regras, mas cada execução aplica somente as regras habilitadas aos arquivos indicados. Sem uma configuração que altere a seleção, o Ruff habilita por padrão as famílias E4, E7, E9 e F.
Uma configuração existente pode mudar esse conjunto. Portanto, “nenhum diagnóstico encontrado” significa apenas que nenhum problema foi identificado dentro dos arquivos e das regras considerados naquela execução.
A seleção de regras funciona como um filtro: primeiro existem as regras disponíveis; depois vêm as habilitadas; por fim aparecem apenas os diagnósticos encontrados no arquivo analisado.

Regras disponíveis → regras selecionadas → diagnósticos encontrados no arquivo.
Para verificar explicitamente F401, F821 e F841 em analise.py, execute o comando abaixo na pasta em que o arquivo está salvo.
python -m ruff check analise.py --select F401,F821,F841Dica
Nesse comando, --select define a seleção como essas três regras. Ele não habilita todo o catálogo e não significa simplesmente acrescentá-las ao conjunto padrão. O resultado também continua limitado a analise.py.
Se python -m ruff check analise.py --select F401,F821,F841 não produzir diagnósticos, isso comprova que o Ruff executou todas as regras disponíveis sobre o projeto inteiro.

Passo 5 de 8
Use a prévia do Ruff, revise as alterações propostas, aplique apenas correções adequadas e confirme o resultado com lint e testes.
Alguns diagnósticos do Ruff têm correção automática; outros exigem uma decisão manual baseada na intenção do programa. A disponibilidade de uma correção não elimina a revisão.
O comando python -m ruff check analise.py --diff apresenta uma prévia das correções aplicáveis sem gravar o arquivo. Em um diff, linhas com - seriam removidas e linhas com + seriam acrescentadas. Confirme se essas mudanças preservam o comportamento esperado.
A correção automática deve passar por uma etapa de revisão antes de ser aplicada.

Primeiro visualize a diferença; depois decida, aplique e verifique.
Atenção
Por padrão, --fix aplica correções classificadas como seguras pelo Ruff. A opção --unsafe-fixes também permite correções classificadas como inseguras e exige cautela adicional; não a use nesta prática. Mesmo uma correção classificada como segura não garante todos os requisitos do programa, e nem todo diagnóstico pode ser resolvido automaticamente.
Em uma pasta dedicada, salve os arquivos abaixo como analise.py e test_analise.py. O exemplo contém uma importação sem uso e um nome indefinido. O teste registra o comportamento esperado para o desconto.
import math
def calcular_total(precos, aplicar_desconto=False):
subtotal = sum(precos)
desconto = subtotal * 0.10
if aplicar_desconto:
return total - desconto
return subtotal
from analise import calcular_total
def test_total_sem_desconto():
assert calcular_total([40.0, 60.0]) == 100.0
def test_total_com_desconto():
assert calcular_total([40.0, 60.0], aplicar_desconto=True) == 90.0
Execute na pasta que contém os dois arquivos. Essa execução normal mostra tanto o F401 quanto o F821.
python -m ruff check analise.pyExecute --diff e procure a remoção de import math. Ela é coerente porque o módulo não participa do cálculo. A prévia mostra somente correções aplicáveis e não substitui a execução normal usada para listar os diagnósticos restantes.
Depois da revisão, aplique as correções disponíveis com --fix e abra novamente analise.py para conferir o resultado.
python -m ruff check analise.py --diff
python -m ruff check analise.py --fixColoque as ações na ordem adequada.
Depois de --fix, execute novamente o Ruff. O F401 deve ter desaparecido, mas o F821 referente a total permanece. Execute também os testes: o cenário com desconto falha porque esse nome não existe.
A intenção registrada pelo teste indica que o desconto deve ser subtraído de subtotal. Corrija manualmente a linha para return subtotal - desconto e repita as duas verificações.
# Em analise.py, troque:
# return total - desconto
# por:
# return subtotal - desconto
python -m ruff check analise.py
python -m pytestQual alteração o Ruff aplicou automaticamente? O que permaneceu para correção manual e qual foi o resultado final de python -m pytest?
Escreva pelo menos 80 caracteres (0/80).

Passo 6 de 8
Diferencie uma supressão pontual e documentada de tentativas de esconder defeitos reais.
Uma supressão instrui o Ruff a não apresentar um diagnóstico, mas não altera o comportamento do programa. Ela só é adequada quando o código é intencional e existe uma justificativa clara para manter a situação indicada.
Aqui, a importação serve somente para verificar se o módulo está disponível. O comentário limita a supressão a F401, e a linha anterior registra a intenção.
def tem_tomllib():
try:
# Importação intencional: verifica a disponibilidade do módulo.
import tomllib # noqa: F401
except ImportError:
return False
return TruePrefira # noqa: F401 na própria linha diagnosticada. Um # noqa sem código pode ocultar outros problemas presentes na mesma linha, dificultando revisões futuras.

A supressão específica afeta apenas a regra indicada; uma supressão ampla pode esconder diagnósticos não relacionados.
Atenção
Uma supressão não define um nome que não existe nem faz um resultado esquecido participar do retorno. Usar noqa para esconder F821 ou F841 sem uma justificativa real apenas remove o aviso; o problema do código permanece.
Qual situação apresenta o uso mais criterioso de noqa?

Passo 7 de 8
Compare o alcance do lint, da verificação de tipos e dos testes para interpretar corretamente resultados positivos.
Quando o Ruff não apresenta diagnósticos, a conclusão correta é limitada: nenhuma das regras habilitadas encontrou um problema nos arquivos analisados, considerando também eventuais supressões. Isso não comprova que todos os resultados do programa estejam corretos.
As ferramentas observam aspectos diferentes:
Elas se complementam, mas nenhuma fornece, sozinha, uma prova geral de correção.

Lint, verificação de tipos e testes examinam propriedades diferentes e têm alcances limitados.
Crie os dois arquivos abaixo na mesma pasta. A função não contém F401, F821 nem F841, mas sua operação está errada: ela aumenta o preço quando deveria aplicar um desconto.
def aplicar_desconto(preco, percentual):
return preco + preco * percentual / 100
from analise import aplicar_desconto
def test_aplica_desconto_de_dez_por_cento():
assert aplicar_desconto(100, 10) == 90
O Ruff não deve encontrar as três regras selecionadas em analise.py. Já o pytest deve mostrar que o resultado obtido é 110.0, e não 90.
python -m ruff check analise.py --select F401,F821,F841
python -m pytest
Se o Ruff não encontra F401, F821 nem F841 em um arquivo, isso comprova que as regras selecionadas não detectaram esses padrões nesse arquivo — mas não que o programa produz resultados corretos.
Como um lint sem diagnósticos pode coexistir com um teste que falha neste exemplo? Explique a responsabilidade de cada verificação.
Escreva pelo menos 80 caracteres (0/80).

Passo 8 de 8
Conclua uma revisão local com Ruff, corrija os diagnósticos conforme a intenção do código e confirme o comportamento com pytest.
Crie uma pasta dedicada e salve nela os dois arquivos abaixo. O contrato é simples: calcular_total deve devolver a soma dos preços menos o desconto. Primeiro execute o Ruff sem modificar o código e classifique os diagnósticos encontrados.
Salve este conteúdo no arquivo pedidos.py.
import json
def calcular_total(precos, desconto):
subtotal = sum(precos)
total = subtotal - desconto
mensagem = f"Total: {total:.2f}"
return tota
Salve o teste na mesma pasta.
from pedidos import calcular_total
def test_calcular_total_aplica_desconto():
resultado = calcular_total([10.0, 20.0], 5.0)
assert resultado == 25.0
Execute os comandos na pasta dos arquivos. Relacione cada F401, F821 e F841 à linha correspondente. Use --diff para examinar as correções automáticas disponíveis sem gravar o arquivo. Se as alterações respeitarem o contrato, aplique-as com --fix; depois faça manualmente as correções restantes. Neste caso, uma supressão só seria adequada se houvesse uma intenção real e documentável — não use noqa apenas para obter uma saída limpa.
Revise o arquivo depois de --diff e novamente depois de --fix. A disponibilidade exata de correções pode variar conforme a versão do Ruff.
python -m ruff check pedidos.py
python -m pytest
python -m ruff check pedidos.py --diff
python -m ruff check pedidos.py --fix
# Faça no editor as correções manuais ainda necessárias.
python -m ruff check pedidos.py
python -m pytest
Uma saída limpa só ganha significado quando você conhece o arquivo analisado, as regras executadas e as mudanças realizadas.

O ciclo termina com uma nova execução do lint e dos testes, não com a simples remoção das mensagens.
Relate os diagnósticos encontrados, justifique cada alteração e informe os resultados da última execução do Ruff e do pytest. Termine explicando por que esses resultados não provam que o programa esteja correto em todos os casos.
Escreva pelo menos 180 caracteres (0/180).
Resumo
A revisão combina diagnóstico estático, decisão humana e verificação de comportamento.
Parabéns! Você concluiu: Analisar estilo e possíveis defeitos com Ruff
100 XP
Você concluiu este nível!
Agora você vai iniciar: Funções de alta ordem e decoradores
Passar funções como argumentosAo concluir, você será capaz de receber funções como parâmetros para variar o comportamento de uma operação e personalizar a ordenação de listas.Milhares de cursos online em vídeo, ebooks e áudiobooks.
Para testar seus conhecimentos no decorrer dos cursos online
Gerado diretamente na galeria de fotos do seu celular e enviado ao seu e-mail
Baixe nosso aplicativo pelo QR Code ou pelos links abaixo:.
+ de 10 milhões
de alunos
Certificado grátis e
válido em todo o Brasil
60 mil exercícios
gratuitos
4,8/5 classificação
nas lojas de apps
Cursos gratuitos em
vídeo, ebooks e audiobooks