Vulture 发现 Python 程序中未使用的代码。这对于清理和查找大型代码库中的错误非常有用。如果您在库和测试套件上运行 Vulture,您可以找到未经测试的代码。
由于 Python 的动态特性,像 Vulture 这样的静态代码分析器可能会错过一些死代码。此外,仅隐式调用的代码可能会报告为未使用。尽管如此,Vulture 仍然是一个非常有用的工具,可以提高代码质量。
--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.
提供的参数可以是 Python 文件或目录。对于每个目录,Vulture 都会分析所有包含的*.py文件。
找到并删除死代码后,再次运行 Vulture,因为它可能会发现更多死代码。
除了查找未使用的函数、类等之外,Vulture 还可以检测无法访问的代码。每个死代码块都会被分配一个介于 60% 到 100% 之间的置信度值,其中 100% 的值表示该代码肯定不会被执行。低于 100% 的值是对代码未使用的可能性的非常粗略的估计(基于代码块的类型)。
代码类型 | 置信值 |
---|---|
函数/方法/类参数,无法访问的代码 | 100% |
进口 | 90% |
属性、类、函数、方法、属性、变量 | 60% |
您可以使用--min-confidence
标志来设置报告为未使用的代码的最小置信度。使用--min-confidence 100
仅报告保证在分析的文件中未使用的代码。
当 Vulture 错误地将代码块报告为未使用时,您可以使用多种选项来抑制误报。如果修复误报也能让其他用户受益,请提交问题报告。
推荐的选项是将报告为未使用的已用代码添加到 Python 模块,并将其添加到扫描路径列表中。要自动获取这样的白名单,请将--make-whitelist
传递给 Vulture:
$ vulture mydir --make-whitelist > whitelist.py
$ vulture mydir whitelist.py
请注意,生成的whitelist.py
文件将包含有效的Python 语法,但为了让Python 能够运行它,您通常需要进行一些修改。
我们在vulture/whitelists/
中收集常见 Python 模块和包的白名单(欢迎拉取请求)。
如果您想忽略整个文件或目录,请使用--exclude
参数(例如--exclude "*settings.py,*/docs/*.py,*/test_*.py,*/.venv/*.py"
)。排除模式与绝对路径进行匹配。
为了与 flake8 兼容,Vulture 支持 F401 和 F841 错误代码,以忽略未使用的导入 ( # noqa: F401
) 和未使用的局部变量 ( # noqa: F841
)。但是,我们建议使用白名单而不是noqa
注释,因为noqa
注释会增加代码的视觉干扰并使其难以阅读。
您可以使用--ignore-names foo*,ba[rz]
让 Vulture 忽略所有以foo
开头的名称以及名称bar
和baz
。此外, --ignore-decorators
选项可用于忽略用给定装饰器装饰的函数名称(但不是它们的参数或函数体)。这在 Flask 项目中很有用,您可以使用--ignore-decorators "@app.route"
来忽略带有@app.route
装饰器的所有函数名称。请注意,Vulture 简化了它无法解析的装饰器: @foo.bar(x, y)
变为“@foo.bar”, @foo.bar(x, y).baz
在内部变为“@”。
我们建议尽可能使用白名单而不是--ignore-names
或--ignore-decorators
,因为白名单在传递给 Vulture 时会自动检查语法正确性,通常您甚至可以将它们传递给 Python 解释器并让它检查所有白名单代码实际上仍然存在于您的项目中。
在某些情况下,您不能仅删除未使用的变量,例如函数签名中的变量。推荐的解决方案是使用del
关键字,如 PyLint 手册和 StackOverflow 上所述:
def foo ( x , y ):
del y
return x + 3
Vulture 还将忽略所有以下划线开头的变量,因此您可以使用_x, y = get_pos()
来标记未使用的元组赋值或函数参数,例如def foo(x, _y)
。
使用--min-confidence
标志提高最小置信度值。
如果 Vulture 抱怨类似if False:
代码,您可以使用布尔标志debug = False
并编写if debug:
来代替。这使得代码更具可读性并让 Vulture 保持沉默。
参见#216。例如,我们建议使用而不是def foo(arg: "Sequence"): ...
from __future__ import annotations
def foo ( arg : Sequence ):
...
您还可以将命令行参数存储在pyproject.toml
tool.vulture
部分下。只需删除前导破折号并将所有剩余破折号替换为下划线即可。
命令行上给出的选项优先于pyproject.toml
中的选项。
配置示例:
[ 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
Vulture 会自动在当前工作目录中查找pyproject.toml
。
要在另一个目录中使用pyproject.toml
,可以使用--config path/to/pyproject.toml
标志。
您可以使用预提交挂钩在每次提交之前运行 Vulture。为此,请安装预提交并将以下内容添加到存储库中的.pre-commit-config.yaml
文件中:
repos :
- repo : https://github.com/jendrikseipp/vulture
rev : ' v2.3 ' # or any later Vulture version
hooks :
- id : vulture
然后运行pre-commit install
。最后,在存储库中创建一个pyproject.toml
文件,并指定 Vulture 应在[tool.vulture] --> paths
下检查的所有文件(参见上文)。
还有一个针对 Vulture 的 GitHub Action,您可以通过编程方式使用 Vulture。例如:
import vulture
v = vulture . Vulture ()
v . scavenge ([ '.' ])
unused_code = v . get_unused_code () # returns a list of `Item` objects
Vulture 使用ast
模块为所有给定文件构建抽象语法树。在遍历所有语法树时,它记录已定义和使用的对象的名称。然后,它报告已定义但未使用的对象。此分析忽略范围,仅考虑对象名称。
Vulture 还通过在return
、 break
、 continue
和raise
语句之后查找代码以及搜索无法满足的if
和while
条件来检测无法访问的代码。
使用--sort-by-size
选项时,Vulture 按行数对未使用的代码进行排序。这有助于开发人员确定首先在何处查找死代码的优先顺序。
考虑以下 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 ()
呼叫:
$ vulture dead_code.py
产生以下输出:
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)
Vulture 正确地将os
和message
报告为未使用,但它无法检测到实际使用了greet
。处理此类误报的推荐方法是创建白名单 Python 文件。
准备白名单
在白名单中,我们模拟变量、属性等的使用。对于上面的程序,白名单可能如下所示:
# whitelist_dead_code.py
from dead_code import Greeter
Greeter . greet
或者,您可以将--make-whitelist
传递给 Vulture 并获取自动生成的白名单。
将原始程序和白名单传递给 Vulture
$ vulture dead_code.py whitelist_dead_code.py
让 Vulture 忽略greet
方法:
dead_code.py:1: unused import 'os' (90% confidence)
dead_code.py:8: unused variable 'message' (60% confidence)
退出代码 | 描述 |
---|---|
0 | 没有发现死代码 |
1 | 输入无效(文件丢失、语法错误、编码错误) |
2 | 无效的命令行参数 |
3 | 发现死代码 |
请访问 https://github.com/jendrikseipp/vulture 报告任何问题或提出拉取请求。