コールグラフを描く

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

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

これを描画するにはどうすればよいですか?この種の動作/コードを文書化するには、どのような種類のチャート/グラフが適切でしょうか?

したがって、UML図を描画するのに役立つとは思いません。 、どちらもフローチャート。コールグラフ、多分?

コメント

  • doxygen-コール/発信者グラフを生成しますI ' Pythonに対してどれだけのサポートがあるかわかりません。 Pythonコードを文書化できることは知っています。
  • ' pycallgraphを試しましたが、'も同様です。複雑/深すぎて使用できません。これは、プレーンなpythonとdjango、およびAPIurlへの外部呼び出しが混在しているためコードが複雑なためです。だから、必要な部分だけを考えて手で描きたかったのです。問題は、'システムを完全に理解するために使用するグラフの種類がわからないことです
  • これが単にシステムを理解するのに役立つ場合、自然に来るものは何でも描くだけです。 'が正式なドキュメントになっている場合は、後でいつでも整理できます。

回答

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

1つを構築するのは簡単です:

  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_にボックスが作成されることに注意してください。除算。メソッド呼び出しの範囲を示します。この簡単な例では、これが実行される唯一のものであるため、ボックスはシーケンス図の高さ全体になります。

ここに画像の説明を入力

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

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

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

enterここに画像の説明

注意事項

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

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

コメント

  • ありがとう、シーケンス図は知っていますが、おっとに適していると私には感じています。私の場合、物事はもう少し厄介です。つまり、たとえば、複数のモジュールに約20の関数/ヘルパーが分散しています。関数が属するモジュールを指定するにはどうすればよいですか?一部の関数もインポート中に名前が変更されることを考えると..
  • モジュールの数は関係ありません。上記の例でも、まったく問題ありません。 ModuleA / function1、ModuleB / Function2など、後で見つけられるように名前を付けるだけです。20の関数の場合、それは大きくなりますが、理解することは間違いなく不可能ではありません。もう1つの考えは、関数の最後の使用後に関数の行を終了し、その下に別の関数の行を配置して、ダイアグラムの水平方向のスペースを節約することです。

回答

コールグラフが最も適切な視覚化だと思います。手作業で行わないことにした場合は、Pythonファイルで静的分析を行い、graphvizドットを使用して視覚化されたコールグラフを生成できるpyanという小さなツールがあります。 ファイル(画像にレンダリングできます)。いくつかのフォークがありますが、最も完全な機能を備えたものは 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」を使用すると、グラフをよりクリーンにできます。 関数が定義された場所を示す線。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です