在大型python项目中查找死代码

Bri*_*tow 67 python pylint code-cleanup

我见过如何在Python代码中找到未使用的函数?但那真的很旧,并没有真正回答我的问题.

我有一个包含多个库的大型python项目,这些库由多个入口点脚本共享.多年来,这个项目已经吸引了许多作者,所以有很多死代码.你知道该怎么做.

我知道找到所有死代码是不可判定的.我所需要的只是一个工具,可以找到所有未被调用的函数.我们没有根据函数名称的字符串调用函数做任何事情,所以我并不担心任何病态......

我刚刚安装了pylint,但它似乎是基于文件的,并没有太多关注文件间依赖关系,甚至是函数依赖关系.

很明显,我可以在所有文件中使用gre,从中获取所有函数名称,并为每个函数名称执行grep.我只是希望有一些比那里更聪明的东西.

ETA:请注意,我不希望或想要完美的东西.我知道我的停止问题证明就像任何人一样(当我看到递归可枚举的东西时,我真的没有教过计算理论).任何试图通过实际运行代码来逼近它的东西都会花费太长时间.我只是想要在语法上通过代码的东西并说"这个函数是肯定使用的.可以使用这个函数,这个函数绝对不使用,其他人甚至似乎都不知道它存在!" 前两个类别并不重要.

Kei*_*han 36

你可能想尝试秃鹰.由于Python的动态特性,它无法捕捉到所有内容,但它可以捕获相当多而不需要像coverage.py这样的完整测试套件,而其他需要工作.


Pet*_*ood 15

尝试运行Ned Batcheldercoverage.py.

Coverage.py是一种用于测量Python程序代码覆盖率的工具.它监视您的程序,注意代码的哪些部分已被执行,然后分析源代码以识别可能已执行但未执行的代码.

  • 这将涉及在所有可能的配置中运行代码.我不想这样做.我不想要所有死代码的完整列表.我只想要快速而肮脏的近似.留下一些死代码很好. (5认同)
  • "留下一些死代码很好" - 我真的不认为这很好. (2认同)

Sve*_*ach 8

即使代码没有做任何花哨的东西,也很难确定在不执行代码的情况下调用哪些函数和方法.普通函数调用很容易检测,但方法调用真的很难.只是一个简单的例子:

class A(object):
    def f(self):
        pass

class B(A):
    def f(self):
        pass

a = []
a.append(A())
a.append(B())
a[1].f()
Run Code Online (Sandbox Code Playgroud)

没什么特别会在这里,但试图确定是否有任何脚本A.f()B.f()称为会有一个相当困难的时间,而无需实际执行代码这样做.

虽然上面的代码没有做任何有用的事情,但它肯定使用出现在实际代码中的模式 - 即将实例放在容器中.真正的代码通常会做更复杂的事情 - 酸洗和去除,分层数据结构,条件.

如前所述,只需检测表单的普通函数调用

function(...)
Run Code Online (Sandbox Code Playgroud)

要么

module.function(...)
Run Code Online (Sandbox Code Playgroud)

会很容易的.您可以使用该ast模块来解析源文件.您将需要记录所有导入以及用于导入其他模块的名称.您还需要跟踪顶级函数定义和这些函数内的调用.这将为您提供依赖关系图,您可以使用NetworkX检测此图的连接组件.

虽然这可能听起来相当复杂,但它可能只用不到100行代码完成.不幸的是,几乎所有主要的Python项目都使用类和方法,所以它几乎没有帮助.


Bri*_*tow 6

这是我至少暂时使用的解决方案:

grep 'def ' *.py > defs
# ...
# edit defs so that it just contains the function names
# ...
for f in `cat defs` do
    cat $f >> defCounts
    cat *.py | grep -c $f >> defCounts
    echo >> defCounts
done
Run Code Online (Sandbox Code Playgroud)

然后我看一下参考文献很少的个别函数(<3说)

它很难看,而且它只给出了大致的答案,但我认为这对于一个开始来说已经足够了.你们有什么想法?