77

Pythonコードで未使用の関数を見つけるにはどうすればよいですか? しかし、それは本当に古く、私の質問にはあまり答えていません。

複数のエントリ ポイント スクリプトによって共有される複数のライブラリを含む大規模な Python プロジェクトがあります。このプロジェクトは何年にもわたって多くの作成者によって積み上げられてきたため、大量のデッド コードが存在します。あなたはドリルを知っています。

すべてのデッド コードを見つけることは決定不可能であることはわかっています。必要なのは、どこにも呼び出されていないすべての関数を見つけるツールだけです。関数名の文字列に基づいて関数を呼び出すことは何もしていないので、病的な心配はありません...

pylintをインストールしたばかりですが、ファイルベースのようで、ファイル間の依存関係や関数の依存関係にもあまり注意を払っていません。

明らかに、すべてのファイルで def を grep し、そこからすべての関数名を取得し、それらの関数名ごとに grep を実行できます。それよりも少し賢いものが既にあることを願っています。

ETA: 完璧なものを期待したり望んだりしていないことに注意してください。私は自分の停止問題の証明を誰とでも同じように知っています (実際には、再帰的に列挙可能なものを見ているときに知っている計算理論を教えました)。実際にコードを実行して概算しようとすると、時間がかかりすぎます。構文的にコードを調べて、「この関数は間違いなく使用されています。この関数は使用される可能性があり、この関数は間違いなく使用されていません。誰もそれが存在することを知らないようです!」最初の 2 つのカテゴリは重要ではありません。

4

7 に答える 7

44

vultureを試してみてください。Python の動的な性質により、すべてをキャッチすることはできませんが、coverage.py などの完全なテスト スイートを必要とせずに、かなりの部分をキャッチできます。

于 2013-08-14T14:17:47.350 に答える
16

Ned Batcheldercoverage.pyを実行してみてください。

Coverage.py は、Python プログラムのコード カバレッジを測定するためのツールです。プログラムを監視し、コードのどの部分が実行されたかを確認し、ソースを分析して、実行された可能性があるが実行されなかったコードを特定します。

于 2012-03-01T22:22:24.867 に答える
9

コードが派手なことをしていなくても、コードを実行せずにどの関数とメソッドが呼び出されたかを判断するのは非常に困難です。単純な関数の呼び出しは比較的簡単に検出できますが、メソッドの呼び出しは非常に困難です。簡単な例:

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

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

a = []
a.append(A())
a.append(B())
a[1].f()

A.f()ここでは特別なことは何も行っていませんが、実際にコードを実行しないと、またはB.f()が呼び出されたかどうかを判断しようとするスクリプトはかなり困難です。

上記のコードは何の役にも立ちませんが、確かに実際のコードに見られるパターンを使用しています。つまり、インスタンスをコンテナに配置しています。実際のコードは通常、さらに複雑なことを行います - ピクルとアンピクル、階層データ構造、条件分岐。

前に述べたように、フォームの単純な関数呼び出しを検出するだけです

function(...)

また

module.function(...)

かなり簡単になります。モジュールを使用してast、ソース ファイルを解析できます。すべてのインポートと、他のモジュールのインポートに使用される名前を記録する必要があります。また、トップレベルの関数定義とこれらの関数内の呼び出しを追跡する必要があります。これにより、依存関係グラフが得られ、NetworkXを使用して、このグラフの接続されたコンポーネントを検出できます。

これはかなり複雑に聞こえるかもしれませんが、おそらく 100 行未満のコードで実行できます。残念ながら、ほとんどすべての主要な Python プロジェクトはクラスとメソッドを使用しているため、ほとんど役に立ちません。

于 2012-03-02T16:58:17.273 に答える
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

次に、参照がほとんどない個々の関数を調べます (< 3 と言います)。

見苦しく、おおよその答えしか得られませんが、最初は十分だと思います。皆さんはどうお考えですか?

于 2012-03-02T16:13:43.660 に答える
4

次の行では、明らかに属性、関数呼び出し、デコレータ、または戻り値として使用されていないすべての関数定義を一覧表示できます。したがって、それはおおよそあなたが探しているものです。完璧ではなく、遅いですが、誤検知はありませんでした. (Linux の場合は に置き換える必要がありackますack-grep)

for f in $(ack --python --ignore-dir tests -h --noheading "def ([^_][^(]*).*\):\s*$" --output '$1' | sort| uniq); do c=$(ack --python -ch "^\s*(|[^#].*)(@|return\s+|\S*\.|.*=\s*|)"'(?<!def\s)'"$f\b"); [ $c == 0 ] && (echo -n "$f: "; ack --python --noheading "$f\b"); done
于 2013-08-06T13:57:17.643 に答える
1

単純なpylintプラグインで非常に迅速に達成できるIMO:

  • S1セット内の分析された各関数/メソッド(/クラス?)を覚えておいてください
  • S2セット内の呼び出された各関数/メソッド(/クラス?)を追跡します
  • レポートにS1-S2を表示する

次に、意味のあるものを取得するには、すべてのコードベースでpylintを呼び出す必要があります。もちろん、前述のように、推論の失敗などが誤検知を引き起こす可能性があるため、これを確認する必要があります。とにかく、それはおそらく実行されるgrepの数を大幅に減らすでしょう。

私はまだ自分でそれをする時間はあまりありませんが、誰もがpython-projects@logilab.orgメーリングリストで助けを見つけるでしょう。

于 2012-03-02T08:14:39.333 に答える
1

多くのテストでコードをカバーしている場合 (非常に便利です)、コード カバレッジ プラグインを使用してそれらを実行すると、未使用のコードが表示されます。)

于 2012-03-01T22:23:29.810 に答える