とあるメーカーエンジニアの趣味備忘録

Python, マイコンいじり, 日々の呟きなど

Python でパッケージやクラス間の依存関係を可視化してみた.[Pyreverse]

Python でも他のプログラミング言語でも,割と大きめのプロジェクトを作成している際に直面しやすい問題として次の問題があると感じる.  

「トップのクラスは一体どのクラスとどのクラスとどのパッケージを読み込んでいて,さらに,その読み込まれた元のクラスは一体どのクラスとどのクラスとどのパッケージを読み込んでいたんだろうか...」

そう,パッケージ間やクラス間の依存関係が分からなくなってしまうのである.
(チームで開発するときや仕事で開発するときなど,設計の時点でしっかりと概念図やクラス図等を作成していればそのようなことは回避できる!と言われたらぐうの音も出ないというやつだが.自分のような初心者&個人開発者にとっては,最初の方は同じディレクトリ下に次々とソースファイルを作って後から見たら,どれとどれがメインファイルで,どれがサブ的なファイルだろうか...みたいな状況になりかねない気がする.)

とりあえず,クラス間の依存関係をとにもかくにも整理したかったのである.
そこでググっていたら次のような記事がヒットした.

Python - Pythonでモジュールの依存関係図を描きたい|teratail

要するに,ここで質問している人も自分と同じような機能を実現したいと考えていて質問しており,
"pylint による pyreverse を使ったらイイよ!"
と言われているのである.

で,pyreverse を導入する手順について

linuxBean14.04(49)pyreverseでPythonコードからUML図を生成

上のリンクに説明されていたので,その通りに導入してみた.
因みに,私の環境は,Python3.6で実行環境はAnaconda Prompt(Windows 10)である.

先ず,pylint をインストールする.

conda install pylint

次に,pyreverse がきちんと動作するのかを確かめるために,次の公式ドキュメントに載っていたコードを実行してみた.

Pyreverse : UML Diagrams for Python (Logilab.org)

pyreverse -o png -p Pyreverse pylint/pyreverse/

すると,その実行結果が

The output format 'output.png' is currently not available. Please install 'Graphviz' to have other output formats than 'dot' or 'vcg'.

どうやら,"Graphviz"というパッケージがインストールされていないようなのである.
この問題に関しては,stackoverflowにQ&Aが投稿されていた.

python - Pyreverse complaining even after having Graphviz - Stack Overflow

要するに,インストールしたうえで,パスを通せばよいということなのである.
なので,

conda install graphviz

でインストールを行い,
パスを通した.
graphvizのパスは

C:\Program Files (x86)\Graphviz2.38\bin

であるので,これを環境変数PATHに追加した.
そして,実行すると又エラー
以下のリンクにヒントとなることが書いてあった.
Windows の Anaconda 環境で pyreverse がエラーになる場合の対策 | 南房総ツーリング日記

どうやら,対策としてPATH 環境変数Graphviz のパスを定義しておけば、サブプロセスにも PATH 環境変数が引き継がれる。その結果、サブプロセスでも dot コマンドを実行することができるようになる。
らしい.(windowsのパスとanacondaのパスは何か違うのかもしれない.)

set PATH=%PATH%;%GRAPHVIZ_DOT%\..

を実行して,anaconda promptを再起動して実行してみたら上手くいった.

そして,上にも載せたpyreverseの公式ドキュメントは英語で書かれているため,その内容に関して備忘録をここにまとめておく.

Introduction
Pyreverse builds a diagram representation of the source code with:
class attributes, if possible with their type
class methods
inheritance links between classes
association links between classes
representation of Exceptions and Interfaces

先ず,Introductionの項には,

Pyreverseはソースコードのダイアグラム図表現を出力します.その出力内容は,

  • クラス属性や型(public, privateやint, char等)

  • クラスメソッド

  • クラス間の継承関係

  • クラス間の関連性

  • 例外とインタフェースの表現

となっていると述べられている.

使い方として,

pyreverse -o [出力フォーマット] -p [出力ファイル名] [ターゲットファイル名・ターゲットディレクトリ名] 

を実行することで,次の2つのファイルが作成されるという.

  • Package Diagram

こちらは,packages_[指定したファイル名].[指定した出力拡張子]という形式でファイルが出力されるよう.

  • Class Diagram

こちらは,class_[指定したファイル名].[指定した出力拡張子]という形式でファイルが出力されるよう.

ちなみに,-oと-pはオプションであり,

  • -o [出力フォーマット] : -o png のような形式で指定する.

  • -p [出力ファイル名] : -p pytest のような形式で指定する.

実際に実行してみたところ,

pyreverse Urllist_editor.py

f:id:makutsueeken5:20190213141011j:plain

というファイルが生成された.

どうやらこれはword形式のファイルだそうで,開いてみると, f:id:makutsueeken5:20190213141103j:plain

という画面が出力されたが,いまいちよくわからない.

そこで,

pyreverse -o jpeg -p Urllist_editor Urllist_editor.py

を実行したところ,

f:id:makutsueeken5:20190213141248j:plain

が出力された. どうやら,細かなオプションを指定しないとそのクラスのクラス図とメソッドだけが出力されるようだ.

その他のオプションは以下の通り.

-a N, -A

サーチする親クラスの深さの度合い.小文字で指定する場合は,-a1, -a2のように深さを表す数を指定する. 大文字-Aで指定した場合には,すべての親クラスをサーチする.

-s N, -S    

サーチする関連クラスの深さ度合い.小文字で指定する場合には,-s1, -s2のように深さを表す数値を指定する. 大文字-Sで指定した場合には,すべての関連クラスをサーチする.

-A, -S      

上の大文字バージョンの説明.すべての親クラス,ないしは,関連クラスをサーチする.

-m[yn]      

モジュール名(Pathlibとかurllibとか)が表示されるかされないか.

されてもよい場合は-myと指定して.その結果として"Pathlib.Path"等のようにクラス名のところに表示される.

されてほしくない場合は-mnと指定して,その結果として"Path"のようにクラス名からモジュール名が表示されない形でダイアグラムが作成される.

-f MOD      filter the attributes : PUB_ONLY/SPECIAL/OTHER/ALL

表示する属性値を(メソッドの種類など)をフィルタリングする.

-f PUB_ONLY のようにモードを指定するみたい.

モードは4種類あるようで,

  • PUB_ONLY : パブリックメソッドだけを表示するみたい

  • SPECIAL

  • OTHER

  • ALL : 全ての属性値を表示するようだ.

-k          

属性値もメソッドも表示せずに,クラス名のみを表示していく.

-b          show 'builtin' objects

ビルトインオブジェクトのみを表示する.

pyreverse -ASmy -o png Urllist_editor.py -p Urllist_editor

を実行した結果その出力として次の結果が得られた. f:id:makutsueeken5:20190213144957p:plain