前の関連記事:linuxBean14.04(49)pyreverseでPythonコードからUML図を生成
pyreverseの結果の見方とオプションを使ってみます。
pycallgraphパッケージをpyreverseで解析する
linuxBean14.04(40)pycallgraphでPythonのコールグラフ:その1のpycallgraphと違って/usr/lib/python3.3/site.pyをpyreverseで解析しても単純な図しか生成されず面白くないのでpycallgraphパッケージ、/usr/local/lib/python3.3/dist-packages/pycallgraphをpyreverseで解析することにしました。
どのマシンにもインストールしてあるはずのパッケージpipを解析してみたのですが、時間がかかる上にあまりにも複雑な図が出力されるので例として取り上げるのはやめました。
pyreverse -o 出力ファイル形式 -p プロジェクト名 解析対象
この形式が基本形になります。
-o <format>, --output=<format>
出力ファイル形式を指定します。デフォルトはdotです。
指定できるファイル形式はgraphviz/dotがわかる形式と同じでdot -Txxxとコマンドを打つとその形式がわかります。
pq@pq-VirtualBox:~$ dot -Txxx Format: "xxx" not recognized. Use one of: canon cmap cmapx cmapx_np dot eps fig gd gd2 gif gv imap imap_np ismap jpe jpeg jpg pdf pic plain plain-ext png pov ps ps2 svg svgz tk vml vmlz vrml wbmp x11 xdot xdot1.2 xdot1.4 xlibよくわからなければpngを指定しておくのが無難でしょう。
-p <project name>, --project=<project name>
プロジェクト名を指定します。デフォルトはNo Nameです。
このプロジェクト名は出力ファイル名に利用されます。
解析対象にフォルダを指定している場合はclassesファイルとpackagesファイルが出力され、それぞれのファイル名がclasses_プロジェクト名.png、packages_プロジェクト名.png(ファイル形式をpngに指定した場合)になります。
プロジェクト名のスペースはアンダーバーに置換されます。
ですのでプロジェクト名オプションを指定しない場合はデフォルトのNo Nameが使われ、classes_No_Name.png、packages_No_Name.pngが出力されます。
解析対象
フォルダを指定した場合はその中にあるサブフォルダを含めたすべてのpyファイルが解析され、classesファイルとpackagesファイルが出力されます。
pyファイルを指定した場合はclassesファイルのみ出力されます。
早速pycallgraphパッケージを解析してみましょう。
pyreverse -o png -p Pycallgraph /usr/local/lib/python3.3/dist-packages/pycallgraph
pq@pq-VirtualBox:~$ pyreverse -o png -p Pycallgraph /usr/local/lib/python3.3/dist-packages/pycallgraph parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/__init__.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/globbing_filter.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/config.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/pycallgraph.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/memory_profiler.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/exceptions.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/tracer.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/util.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/__init__.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/metadata.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/color.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/output/pickle.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/output/ubigraph.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/output/output.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/output/graphviz.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/output/gephi.py... parsing /usr/local/lib/python3.3/dist-packages/pycallgraph/output/__init__.py...解析対象に指定したフォルダにあるpyファイルがすべてパースされました。
コマンドを実行したフォルダにclasses_Pycallgraph.pngとpackages_Pycallgraph.pngの二つのファイルが出力されました。
packages_Pycallgraph.pngでモジュールの依存関係(親フォルダ以上にあるものは除く)を知る
packages_Pycallgraph.png
packages_Pycallgraph.pngというファイル名なのでこの図は「パッケージ図」といいたいところですが、実際は「モジュール図」になっています。
Pythonではスクリプトを書いたpyファイルがモジュールであり(6. モジュール — Python 3.3.6 ドキュメント)、パッケージとはモジュールの集合体のことをいいます(6.4. パッケージ)。
なのでパッケージ図の定義をパッケージ同士の依存関係を描画したものである(パッケージ図 - Wikipedia)とすると、packages_Pycallgraph.pngはパッケージ同士の依存関係ではなく、モジュール同士の依存関係を描画したものなのでモジュール図ということになります。
依存関係といっても親フォルダにあるものからインポートしたものは表現されていません。
ここでは出力ファイル名にパッケージとついているので、それにならって以下パッケージ図といいます。
パッケージ図には解析対象に指定したフォルダ名とそのサブフォルダ名、パースしたpyファイル名が「フォルダ名.pyファイル名」で出力されています。
__init__.pyファイルはパッケージ図にはでてきませんが、各フォルダに含まれる__init__.pyファイルが各フォルダ名で出力されています。
pycallgraph/__init__.pyではpycallgraph、exceptions、config、globbing_filter、util、colorのモジュールが相対インポート(6.4.2. パッケージ内参照)で読み込まれていますので、パッケージ図ではpycallgraphからそれぞれへ矢印がでています。
パッケージ図では相対モジュール名は絶対モジュール名に置換されています。
pycallgraphからpycallgraph自身へ矢印がでていますが、これは本来pycallgraph.pycallgraphへでるべき矢印と思われます。
pycallgraph/output/__init__.pyからpycallgraph/output/output.pyへの呼び出しは正しく矢印が引かれています。
何回かやり直してみるとpycallgraphからpycallgraph.pycallgprahへの矢印が正しく存在したりしなかったりと一定しませんでした。
pycallgraph/pycallgraph.pyからpycallgraph/output/output.pyにあるOutputクラスがインポートされていますがそれはpycallgraph/output/__init__.py(パッケージ図ではpycallgraph.output)を介して呼び出していることがわかります。
pycallgraph/output/output.pyからは親フォルダにあるexceptionsとcolorをインポートしていますが、親フォルダからのインポートは矢印はでてこないようになっているようです。
classes_Pycallgraph.pngはクラス図
classes_Pycallgraph.png
LibreOffice(8)統一モデリング言語UML(Unified Modeling Language)の学習で学習したやつですね。
先が黒の菱形で連結されているものはコンポジションです。
コンポジションは白の菱形で表現される集約の一種で、ライフサイクルが黒菱形のクラスから生成したインスタンスと一致するという意味です。
例えばColorクラスはGraphvizOutputクラスのインスタンスの中でインスタンス化されて、そのインスタンスはGraphvizOutputインスタンスのgroup_border_colorプロパティになるので、GraphvizOutputクラスとコンポジションで結ばれ、その横にGraphvizOutputでのプロパティ名が緑字で書かれています。
Exceptionは赤字で書かれています。
プロパティの定義時に型がわかるものはその型が表示されています。
PythonではJavaと違って関数はクラス外にも書けるので、クラスの外にある関数は反映されていません。(例:memory_profiler.pyのmemory_usage())
オプションで出力範囲を制限する
-f <mode>, --filter-mode=<mode>
<mode>に対応したフィルターをかけます。
PUB_ONLY: デフォルト、non public属性(=SPECIAL+PRIVATE)をすべてフィルターします。
ALL: フィルター無し。
SPECIAL: コンストラクターを除くPythonの特殊メソッドをフィルターします。
OTHER: protectedとprivate属性をフィルターします。
pyreverse -f ALL -o png -p Pycallgraph /usr/local/lib/python3.3/dist-packages/pycallgraph
「_」から始まる特殊メソッド(索引 — Python 3.3.6 ドキュメント)も出力されています。
今回取り上げたpycallgraphパッケージではPUB_ONLYとSPECIAL、ALLとOTHERは同じ結果でした。
-c <class>, --class=<class>
指定したクラスに関連したクラスのみのクラス図を出力してくれます。
クラス名は-myオプションを指定したときにでてくるモジュール名を付加した名前で指定します。
pyreverse -c pycallgraph.output.pickle.PickleOutput -o png -p Pycallgraph /usr/local/lib/python3.3/dist-packages/pycallgraph
pycallgraph.output.pickle.PickleOutputクラスについてのみ出力されました。
出力ファイル名は「pycallgraph.output.pickle.PickleOutput.png」になっていました。
暗黙的に-ASmyというオプションが付加されているので、A:すべてのクラス名を出力、S:関連クラスをすべて出力、my:クラス名にモジュール名を付加して出力、という状態で出力されます。
-a <ancestor>, --show-ancestors=<ancestor>
プロジェクトにない親クラスの表示階層を数値で指定します。
エラーがでて確認できませんでしたが、その原因は単に今回取り上げた例にプロジェクト外の親クラスがないためだと思われます。
-A, --all-ancestors show all ancestors off all classes in <projects>
プロジェクト内でインスタンス化されているクラスをすべて表示します。
pyreverse -A -o png -p Pycallgraph /usr/local/lib/python3.3/dist-packages/pycallgraph
ArgumentParserとQueue、defaultdictの3つのクラスが新たに出力されています。
これらはプロジェクト内でインスタンス化されていますが、定義はプロジェクト外でされています。
-s <ass_level>, --show-associated=<ass_level>
関連するクラスを表示するレベルを数値で指定します。
pyreverse -s2 -o png -p Pycallgraph /usr/local/lib/python3.3/dist-packages/pycallgraph
-Aオプションの出力結果よりさらに1階層深く出力されています。
-S, --all-associated
再帰的にすべての関連クラスを出力します。
pyreverse -S -o png -p Pycallgraph /usr/local/lib/python3.3/dist-packages/pycallgraph
かなりたくさん出力クラスが増えました。
-b, --show-builtin
ビルトインオブジェクトも出力されるそうですが今回の例ではオプションなしの場合と違いがでませんでした。
-m [yn], --module-names=[yn]
クラス名にモジュール名も追加されます。
pyreverse -my -o png -p Pycallgraph /usr/local/lib/python3.3/dist-packages/pycallgraph
これは結構わかりやすいですね。
-k, --only-classnames
クラス名のみ表示し、属性を表示しません。
pyreverse -k -o png -p Pycallgraph /usr/local/lib/python3.3/dist-packages/pycallgraph
--ignore=<file>
無視するファイルやフォルダ名を指定できます。
pyreverse --ignore=output -o png -p Pycallgraph /usr/local/lib/python3.3/dist-packages/pycallgraph
outputフォルダが無視されました。
参考にしたサイト
Pyreverse : UML Diagrams for Python (Logilab.org)
Pyreverseの開発元のようですが結果の画像のリンクが切れたままになっています。
0 件のコメント:
コメントを投稿