コールグラフを描く


11

私はpythonで書かれた古いコードベースを維持しています。特に、モジュールから他の関数​​を呼び出す他のモジュールから他の関数​​を呼び出す複雑なコードがあります。OOPではなく、単なる関数とモジュールです。
メイン関数を呼び出すたびにフローの開始位置と終了位置を追跡しようとしましたが、サブコールで迷子になるため、これを描画する必要があると感じています。

私が心配しているのは、各関数が自分のタスクを完了し、呼び出し元に値を返すために、体内で複数の外部関数を呼び出すことです。

これをどうやって描くことができますか?この種の動作/コードを文書化するのに適切なチャート/グラフィックの種類は何ですか?

したがって、UMLダイアグラムを作成するのに、フローチャートではなく、役に立つとは思いません。多分コールグラフ?


doxygen-呼び出し/呼び出しグラフを生成しますが、Pythonがどれだけサポートされているかわかりません。Pythonコードをドキュメント化できることを知っています。
gbjbaanb

私はpycallgraphを試しましたが、それを使用するには複雑すぎます/深すぎます。これは、プレーンなpythonとdjangoおよびAPI urlへの外部呼び出しが混在しているため、コードが複雑であるためです。だからこそ、必要な部分だけを考慮して手で描いてみたかったのです。問題は、システムを完全に理解するためにどのようなグラフを使用すればよいかわからないことです。
レオナルド

5
これがあなたがそれを理解するのを助けることだけであるなら、自然に来るものは何でも描いてください。正式なドキュメントになっている場合は、いつでも整理できます。
jonrsharpe

回答:


9

ここで探しているのはシーケンス図だと思います。これらにより、さまざまなモジュールが矢印を使用して相互に呼び出す順序を視覚化できます。

構築は簡単です:

  1. 開始クラスを下に点線で描きます。
  2. 呼び出しトレースで次のクラス/メソッドをその下に点線で描きます
  3. 最後に描いた矢印の下に垂直に配置された矢印で線を接続します
  4. トレース内のすべての呼び出しに対して手順2〜3を繰り返します。

シーケンス図を作成する次のコードがあると仮定します。

def long_division(quotient, divisor):
    solution = ""
    remainder = quotient
    working = ""
    while len(remainder) > 0:
        working += remainder[0]
        remainder = remainder[1:]
        multiplier = find_largest_fit(working, divisor)
        solution += multiplier
        working = calculate_remainder(working, multiplier, divisor)
    print solution


def calculate_remainder(working, multiplier, divisor):
    cur_len = len(working)
    int_rem = int(working) - (int(multiplier) * int (divisor))
    return "%*d" % (cur_len, int_rem)


def find_largest_fit(quotient, divisor):
    if int(divisor) == 0:
        return "0"
    i = 0
    while i <= 10:
        if (int(divisor) * i) > int(quotient):
            return str(i - 1)
        else:
            i += 1


if __name__ == "__main__":
    long_division("645", "5")

最初に描画するのはmain、メソッドに接続するエントリポイント()long_divisionです。これによりlong_divisionにボックスが作成され、メソッド呼び出しのスコープが示されることに注意してください。この単純な例では、実行されるのはこれだけであるため、ボックスはシーケンス図の全体の高さになります。

ここに画像の説明を入力してください

次にfind_largest_fit、作業番号に収まる最大の倍数を見つけてそれを返します。関数呼び出しのスコープを示すためlong_divisionfind_largest_fit、別のボックスでからまで線を引きます。乗数が返されたときにボックスがどのように終了するかに注意してください。これがその関数スコープの終わりです!

ここに画像の説明を入力してください

数回繰り返すと、グラフは次のようになります。

ここに画像の説明を入力してください

ノート

渡された変数名を使用して呼び出しにラベルを付けるか、特定の1つのケースのみを文書化する場合はそれらの値にラベルを付けるかを選択できます。自身を呼び出す関数で再帰を表示することもできます。

さらに、ここにユーザーを表示し、プロンプトを表示して、システムへの入力を簡単に表示できます。これはかなり柔軟なシステムであり、かなり便利だと思います!


おかげで、私はシーケンス図を知っていますが、私にはそれがoopに適していると感じています。私の場合、物事はもう少し面倒です。たとえば、複数のモジュールに約20個の関数/ヘルパーが分散していることを意味します。Hoは、関数が属するモジュールを指定しますか?インポート中に一部の関数の名前も変更されることを考慮する
Leonardo

1
私はあなたが持っているモジュールの数は重要ではないと言うでしょう-上の例はまったくありません。ModuleA / function1、ModuleB / Function2など、後で見つけられるように名前を付けてください。20個の関数については大きくなりますが、理解することは絶対に不可能ではありません。もう1つ考えられることは、関数の最後の使用後にその行を終了し、その下に別の関数の行を配置して、ダイアグラムの水平方向のスペースを節約することです。
アンプト

5

コールグラフが最も適切な視覚化になると思います。手作業で行わないことにした場合pyanは、Pythonファイルで静的分析を実行し、graphvizドットファイル(画像にレンダリングできる)を介して視覚化されたコールグラフを生成できるという、素敵な小さなツールがあります。いくつかのフォークがありましたが、最も完全な機能を備えたものはhttps://github.com/davidfraser/pyanのようです。

コマンドを実行するときに、処理するすべてのファイルを指定するだけです。

python ~/bin/pyan.py --dot a.py b.py c.py -n > pyan.dot; dot -Tpng -opyan.png pyan.dot

または

python ~/bin/pyan.py --dot $(find . -name '*.py') -n > pyan.dot; dot -Tpng -opyan.png pyan.dot

関数が定義された場所を示す線を削除する '-n'を使用して、グラフをきれいにすることができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.