web-dev-qa-db-ja.com

コールグラフを描く

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

気になるのは、各関数が本体内の複数の外部関数を呼び出してタスクを完了し、値を呼び出し元に返すことです。

どうすればこれを描くことができますか?この種の動作/コードを文書化するには、どのようなチャート/グラフィックが適切であることを意味しますか?

ですから、UMLダイアグラムを描画することも、フローチャートを描画することも役に立たないと思います。コールグラフ、たぶん?

12
Leonardo

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

作成は簡単です:

  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")

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

enter image description here

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

enter image description here

数を増やして数を増やし、チャートは次のようになります。

enter image description here

ノート

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

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

9
Ampt

コールグラフが最も適切な視覚化になると思います。手作業で行わない場合は、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」を使用して、グラフをよりクリーンにすることができます。

6
seren