このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

Windows上のPythonでグラフ描画: PyGraphvizインスールで一苦労

事情があって、Pythonで使えるグラフ描画ツールを探しました。いくつか候補があるのですが、NetworkX(http://networkx.lanl.gov/)が良さそうに思えました。

NetworkXは、グラフ描画が主たる目的ではなくて、グラフの操作や解析のためのライブラリです。描画バックエンドは現在 matplotlib, pygraphviz, pydot の3種類をサポートしています(http://networkx.lanl.gov/reference/drawing.html)。PyGrphviz(http://networkx.lanl.gov/pygraphviz/)はNetworkXと同じ開発コミュニティによるもので、NetworkXと類似のAPIを提供してます。描画はPyGraphvizを使おうかな、と。

PyGraphviz is a Python interface to the Graphviz graph layout and visualization package.
PyGraphviz is independent from NetworkX but provides a similar programming interface.


PyGraphvizは、グラフのレイアウト・可視化パッケージであるGraphvizに対するPythonインターフェースです。
PyGraphvizは、NetworkXと独立ではありますが、類似のプログラミングインターフェースを提供しています。

Windowsで使うおうと思ったのですが、FAQ(http://networkx.lanl.gov/pygraphviz/reference/faq.html)によると:

We don’t have Windows development machines but would like to have pygraphviz work on all platforms. If you have success with Windows or would be willing to help test and distribute a Windows installer please drop us a note.


私たちはWindows開発マシンを持ってません。でも、pygraphvizがすべてのプラットフォームで動くだろうと思っています。Windowsでうまくいった方、あるいはWindowsインストーラーの配布やテストに協力してくれる方はご連絡ください。

ウーン、大丈夫かな? まーやってみましょう。

内容:

Graphvizのインストール

まずは、Graphviz(http://www.graphviz.org/)をインストールしておきます。ダウンロードは http://www.graphviz.org/Download_windows.php から。Windows用のインストーラー graphviz-2.28.0.msi があります。

デフォルトだと、C:\Program Files\Graphviz 2.28\ にインストールされますが、空白を含むパスがトラブルに繋がるケースがままあったので、僕は C:\Installed\Graphviz-2.28\ にインストール先を変えました。

Path環境変数の設定が必要かもしれません(そのツールをすぐ後に記述)。コマンドラインからdotとかdottyコマンドが動くようになればOKです。

Graphvizのファイル形式はDOT形式と呼ばれていますが、share/graphviz/graphs/ の下のサンプルを見ると、.dot よりは .gv という拡張子がよく使われているんですね。ヘー。

オマケ:環境変数の設定ツール

新しいソフトウェアをインスールすると、環境変数、特にPathを書き換える必要が多いですね。Windowsでは、コントロールパネルから環境変数を設定できますが、あれは使いにくい! Rapid Environment Editor(http://www.rapidee.com/en/about)てのがけっこう便利です。

パスが不正になってしまう書き間違いを指摘してくれるのがありがたい。UIの言語として日本語もサポートしています。おすすめ。

easy_installでインストール -- 失敗

http://networkx.lanl.gov/pygraphviz/install.html によると、easy_install pygraphviz とするのが一番簡単そうです。

easy_installはPythonのパッケージマネージャー/自動インストールツールですが、なぜかPython自体には含まれていません。インストールツールのインストールが必要になってしまうわけです。http://pypi.python.org/pypi/setuptools#files あたりから適当なファイルをダウンロードします。

easy_installを含むsetuptoolsのインストールは、Windowsインストーラーがあるんで特に問題はないでしょう。で、easy_install pygraphviz としてみたのですが、次のようなエラーメッセージで失敗します

running build_ext
building 'pygraphviz._graphviz' extension
error: Unable to find vcvarsall.bat

自動インストールはあきらめ、事情を調べるために、http://networkx.lanl.gov/download/pygraphviz/ から pygraphviz-1.1.tar.gz をダウンロードしました。

MinGWでコンパイルできるようにする

PyGraphvizには、graphviz_wrap.c というC言語のソースが含まれ、これのコンパイルで失敗しているようです。
Pythonのdistutilsのなかで、MSVCを起動しようとしてるようです。MSVCは入れてないし、入れるのも面倒なので、既に入っているMinGWでなんとかならないでしょうか。

"Building Python extensions for Windows with only free tools" April 19, 2007 (http://boodebr.org/main/python/build-windows-extensions)によると、MinGWでも出来そうです。そのためには、次のように <Pythonのディレクトリ>\lib\distutils\distutils.cfg というファイルを作ります。

[build]
compiler = mingw32

python .\setup.py build としてみると:

The current setting of library_path and include_path is:
library_path=None
include_path=None

Traceback (most recent call last):
  File ".\setup.py", line 93, in <module>
    raise OSError,"Error locating graphviz."
OSError: Error locating graphviz.

ありゃダメだ。library_pathとinclude_pathの設定が必要そうなので、setup.py を編集しました。

library_path='c:/Installed/Graphviz-2.28/lib/release/lib'
include_path='c:/Installed/Graphviz-2.28/include/graphviz'

これでいいだろう。

C:\Installed\MinGW\bin\gcc.exe -mno-cygwin -mdll -O -Wall 
  "-Ic:/Installed/Graphviz 2.28/include/graphviz"
  -IC:\Installed\Python26\include -IC:\Installed\Python26\PC 
  -c pygraphviz/graphviz_wrap.c -o build\temp.win32-2.6\Release\pygraphviz\graphviz_wrap.o
pygraphviz/graphviz_wrap.c: In function `agattr_label':
pygraphviz/graphviz_wrap.c:2855: warning: return makes integer from pointer without a cast

おー、なんかコンパイルしているようだ。

writing build\temp.win32-2.6\Release\pygraphviz\_graphviz.def
Traceback (most recent call last):
  File ".\setup.py", line 146, in <module>
    package_data     = package_data
  File "C:\Installed\Python26\lib\distutils\core.py", line 152, in setup
    dist.run_commands()
  File "C:\Installed\Python26\lib\distutils\dist.py", line 975, in run_commands
    self.run_command(cmd)
  File "C:\Installed\Python26\lib\distutils\dist.py", line 995, in run_command
    cmd_obj.run()
  File "C:\Installed\Python26\lib\distutils\command\install.py", line 577, in run
    self.run_command('build')
  File "C:\Installed\Python26\lib\distutils\cmd.py", line 333, in run_command
    self.distribution.run_command(command)
  File "C:\Installed\Python26\lib\distutils\dist.py", line 995, in run_command
    cmd_obj.run()
  File "C:\Installed\Python26\lib\distutils\command\build.py", line 134, in run
    self.run_command(cmd_name)
  File "C:\Installed\Python26\lib\distutils\cmd.py", line 333, in run_command
    self.distribution.run_command(command)
  File "C:\Installed\Python26\lib\distutils\dist.py", line 995, in run_command
    cmd_obj.run()
  File "C:\Installed\Python26\lib\distutils\command\build_ext.py", line 340, in run
    self.build_extensions()
  File "C:\Installed\Python26\lib\distutils\command\build_ext.py", line 449, in build_extensions
    self.build_extension(ext)
  File "C:\Installed\Python26\lib\distutils\command\build_ext.py", line 531, in build_extension
    target_lang=language)
  File "C:\Installed\Python26\lib\distutils\ccompiler.py", line 769, in link_shared_object
    extra_preargs, extra_postargs, build_temp, target_lang)
  File "C:\Installed\Python26\lib\distutils\cygwinccompiler.py", line 260, in link
    target_lang)
  File "C:\Installed\Python26\lib\distutils\unixccompiler.py", line 218, in link
    libraries)
  File "C:\Installed\Python26\lib\distutils\ccompiler.py", line 1166, in gen_lib_options
    opt = compiler.runtime_library_dir_option (dir)
  File "C:\Installed\Python26\lib\distutils\unixccompiler.py", line 285, in runtime_library_dir_option
    compiler = os.path.basename(sysconfig.get_config_var("CC"))
  File "C:\Installed\Python26\lib\ntpath.py", line 198, in basename
    return split(p)[1]
  File "C:\Installed\Python26\lib\ntpath.py", line 170, in split
    d, p = splitdrive(p)
  File "C:\Installed\Python26\lib\ntpath.py", line 125, in splitdrive
    if p[1:2] == ':':
TypeError: 'NoneType' object is unsubscriptable

ガーン、失敗した

最後はその場しのぎの対処で

失敗の原因を追いかけてみると、/lib/distutils/unixcompiler.py というファイルの次の行に問題があるようです。

    compiler = os.path.basename(sysconfig.get_config_var("CC"))

さらに、lib/distutils/sysconfig.py を見ると、sysconfig.get_config_var は、Windowsで "CC" の値を返すようにななっていません。Windowsプラットフォーム用に初期化をする _init_nt() 関数をその場限りかつ強引に書き換えてしまいました。

def _init_nt():
    """Initialize the module as appropriate for NT"""
    # ...
    # 省略
    # 
    g['CC'] = "gcc.exe" # ここに強引に挿入
    global _config_vars
    _config_vars = g

ひどい対処ではありますが、これでコンパイルはうまくいきます。python .\setup.py install とすれば、PyGraphvizがインスールされます。

チュートリアル(http://networkx.lanl.gov/pygraphviz/tutorial.html)にあったサンプルは実行できたので、これでWindows上でもPyGraphvizが使えるようになりました。息切れしちゃったので、グラフの描き方とかはまたいずれ。