Vulture encontra código não utilizado em programas Python. Isso é útil para limpar e encontrar erros em grandes bases de código. Se você executar o Vulture na sua biblioteca e no conjunto de testes, poderá encontrar código não testado.
Devido à natureza dinâmica do Python, analisadores de código estático como o Vulture provavelmente perderão algum código morto. Além disso, o código que é chamado apenas implicitamente pode ser relatado como não utilizado. No entanto, o Vulture pode ser uma ferramenta muito útil para obter maior qualidade de código.
--sort-by-size
$ pip install vulture
$ vulture myscript.py # or
$ python3 -m vulture myscript.py
$ vulture myscript.py mypackage/
$ vulture myscript.py --min-confidence 100 # Only report 100% dead code.
Os argumentos fornecidos podem ser arquivos ou diretórios Python. Para cada diretório, o Vulture analisa todos os arquivos *.py contidos.
Depois de encontrar e excluir o código morto, execute o Vulture novamente, pois ele pode descobrir mais código morto.
Além de encontrar funções, classes, etc. não utilizadas, o Vulture pode detectar código inacessível. Cada pedaço de código morto recebe um valor de confiança entre 60% e 100%, onde um valor de 100% sinaliza que é certo que o código não será executado. Valores abaixo de 100% são estimativas muito aproximadas (com base no tipo de bloco de código) da probabilidade de o código não ser utilizado.
Tipo de código | Valor de confiança |
---|---|
argumento de função/método/classe, código inacessível | 100% |
importar | 90% |
atributo, classe, função, método, propriedade, variável | 60% |
Você pode usar o sinalizador --min-confidence
para definir a confiança mínima para que o código seja relatado como não utilizado. Use --min-confidence 100
para relatar apenas o código que não será utilizado nos arquivos analisados.
Quando o Vulture relata incorretamente pedaços de código como não utilizados, você tem várias opções para suprimir os falsos positivos. Se corrigir seus falsos positivos também puder beneficiar outros usuários, registre um relatório do problema.
A opção recomendada é adicionar código usado relatado como não utilizado a um módulo Python e adicioná-lo à lista de caminhos verificados. Para obter essa lista de permissões automaticamente, passe --make-whitelist
para o Vulture:
$ vulture mydir --make-whitelist > whitelist.py
$ vulture mydir whitelist.py
Observe que o arquivo whitelist.py
resultante conterá uma sintaxe Python válida, mas para que o Python possa executá -lo, normalmente você terá que fazer algumas modificações.
Coletamos listas de permissões para módulos e pacotes Python comuns em vulture/whitelists/
(solicitações pull são bem-vindas).
Se você quiser ignorar um arquivo ou diretório inteiro, use o parâmetro --exclude
(por exemplo, --exclude "*settings.py,*/docs/*.py,*/test_*.py,*/.venv/*.py"
). Os padrões de exclusão são comparados com caminhos absolutos.
Para compatibilidade com flake8, o Vulture suporta os códigos de erro F401 e F841 para ignorar importações não utilizadas ( # noqa: F401
) e variáveis locais não utilizadas ( # noqa: F841
). No entanto, recomendamos o uso de listas de permissões em vez de comentários noqa
, pois os comentários noqa
adicionam ruído visual ao código e dificultam a leitura.
Você pode usar --ignore-names foo*,ba[rz]
para permitir que o Vulture ignore todos os nomes que começam com foo
e os nomes bar
e baz
. Além disso, a opção --ignore-decorators
pode ser usada para ignorar os nomes das funções decoradas com o decorador fornecido (mas não seus argumentos ou corpo da função). Isso é útil, por exemplo, em projetos Flask, onde você pode usar --ignore-decorators "@app.route"
para ignorar todos os nomes de funções com o decorador @app.route
. Observe que o Vulture simplifica os decoradores que não pode analisar: @foo.bar(x, y)
torna-se "@foo.bar" e @foo.bar(x, y).baz
torna-se "@" internamente.
Recomendamos usar listas de permissões em vez de --ignore-names
ou --ignore-decorators
sempre que possível, uma vez que as listas de permissões são automaticamente verificadas quanto à correção sintática quando passadas para o Vulture e muitas vezes você pode até mesmo passá-las para seu intérprete Python e deixá-lo verificar se todos estão na lista de permissões o código ainda existe em seu projeto.
Existem situações em que você não pode simplesmente remover variáveis não utilizadas, por exemplo, em assinaturas de funções. A solução recomendada é usar a palavra-chave del
conforme descrito no manual do PyLint e no StackOverflow:
def foo ( x , y ):
del y
return x + 3
O Vulture também irá ignorar todas as variáveis que começam com um sublinhado, então você pode usar _x, y = get_pos()
para marcar atribuições de tuplas ou argumentos de função não utilizados, por exemplo, def foo(x, _y)
.
Aumente o valor mínimo de confiança com o sinalizador --min-confidence
.
Se o Vulture reclamar de código como if False:
, você pode usar um sinalizador booleano debug = False
e escrever if debug:
em vez disso. Isso torna o código mais legível e silencia o Vulture.
Veja #216. Por exemplo, em vez de def foo(arg: "Sequence"): ...
, recomendamos usar
from __future__ import annotations
def foo ( arg : Sequence ):
...
Você também pode armazenar argumentos de linha de comando em pyproject.toml
na seção tool.vulture
. Simplesmente remova os travessões iniciais e substitua todos os travessões restantes por sublinhados.
As opções fornecidas na linha de comando têm precedência sobre as opções em pyproject.toml
.
Exemplo de configuração:
[ tool . vulture ]
exclude = [ " *file*.py " , " dir/ " ]
ignore_decorators = [ " @app.route " , " @require_* " ]
ignore_names = [ " visit_* " , " do_* " ]
make_whitelist = true
min_confidence = 80
paths = [ " myscript.py " , " mydir " , " whitelist.py " ]
sort_by_size = true
verbose = true
O Vulture procurará automaticamente um pyproject.toml
no diretório de trabalho atual.
Para usar um pyproject.toml
em outro diretório, você pode usar o sinalizador --config path/to/pyproject.toml
.
Você pode usar um gancho de pré-commit para executar o Vulture antes de cada commit. Para isso, instale o pré-commit e adicione o seguinte ao arquivo .pre-commit-config.yaml
em seu repositório:
repos :
- repo : https://github.com/jendrikseipp/vulture
rev : ' v2.3 ' # or any later Vulture version
hooks :
- id : vulture
Em seguida, execute pre-commit install
. Finalmente, crie um arquivo pyproject.toml
em seu repositório e especifique todos os arquivos que o Vulture deve verificar em [tool.vulture] --> paths
(veja acima).
Há também uma ação GitHub para o Vulture e você pode usar o Vulture programaticamente. Por exemplo:
import vulture
v = vulture . Vulture ()
v . scavenge ([ '.' ])
unused_code = v . get_unused_code () # returns a list of `Item` objects
O Vulture usa o módulo ast
para construir árvores de sintaxe abstratas para todos os arquivos fornecidos. Ao percorrer todas as árvores de sintaxe, ele registra os nomes dos objetos definidos e usados. Depois, reporta os objetos que foram definidos, mas não utilizados. Esta análise ignora escopos e leva em consideração apenas os nomes dos objetos.
O Vulture também detecta código inacessível procurando por código após as instruções return
, break
, continue
e raise
, e procurando por condições if
- e while
insatisfatórias.
Ao usar a opção --sort-by-size
, o Vulture classifica o código não utilizado pelo número de linhas. Isso ajuda os desenvolvedores a priorizar onde procurar primeiro o código morto.
Considere o seguinte script Python ( dead_code.py
):
import os
class Greeter :
def greet ( self ):
print ( "Hi" )
def hello_world ():
message = "Hello, world!"
greeter = Greeter ()
func_name = "greet"
greet_func = getattr ( greeter , func_name )
greet_func ()
if __name__ == "__main__" :
hello_world ()
Chamando:
$ vulture dead_code.py
resulta na seguinte saída:
dead_code.py:1: unused import 'os' (90% confidence)
dead_code.py:4: unused function 'greet' (60% confidence)
dead_code.py:8: unused variable 'message' (60% confidence)
O Vulture relata corretamente os
e message
como não utilizados, mas não consegue detectar que greet
é realmente usado. O método recomendado para lidar com falsos positivos como este é criar um arquivo Python de lista de permissões.
Preparando listas de permissões
Em uma lista de permissões simulamos o uso de variáveis, atributos, etc. Para o programa acima, uma lista de permissões poderia ter a seguinte aparência:
# whitelist_dead_code.py
from dead_code import Greeter
Greeter . greet
Alternativamente, você pode passar --make-whitelist
para o Vulture e obter uma lista de permissões gerada automaticamente.
Passando o programa original e a lista de permissões para o Vulture
$ vulture dead_code.py whitelist_dead_code.py
faz o Vulture ignorar o método greet
:
dead_code.py:1: unused import 'os' (90% confidence)
dead_code.py:8: unused variable 'message' (60% confidence)
Código de saída | Descrição |
---|---|
0 | Nenhum código morto encontrado |
1 | Entrada inválida (arquivo ausente, erro de sintaxe, codificação errada) |
2 | Argumentos de linha de comando inválidos |
3 | Código morto encontrado |
Visite https://github.com/jendrikseipp/vulture para relatar quaisquer problemas ou fazer solicitações pull.