この記事では,pygraphvizの機能を搭載したプログラムをpyinstallerでGUI化して配布する方法を紹介する.
なぜこの記事が必要になるかというと, pyinstallerでGUI化してもgraphvizのpathが見つからなかったり,そもそもpyinstallerでgraphvizのファイルが保存されないことに原因がある.
pygraphvizの導入
windowsに導入するためには,以下のサイトが参考になる.
もっと簡単に、pygraphvizをWindows10 64bitでインストールする(Python3)
環境変数は3つ追加しなければいけない.
一つは,Graphvizのサイトからダウンロードしたファイルのパス.(ex. /path/to/file/Graphviz 2.44.1/bin )
あと2つは,conda でinstall したファイルから,Library/bin と Library/bin/graphviz までの2箇所を追加する必要がある.(ex. /path/to/file/graphviz-2.380hfd603c8_2/Library/bin と /path/to/file/graphviz-2.380hfd603c8_2/Library/bin/graphviz)
condaでinstall しているのでAnacondaの中にファイルは存在する.
これで,pygraphvizを起動することが出来る.
pyinstaller で使えるようにする
windowsにpygraphvizを入れて動かせるような環境にしたとしても,pyinstallerでGUI化したとしても,他のPCで動かそうとすると動かない.
原因としては,fdp.exe, neato.exeなどが見つからないことが挙げられる.
そこで,GUI化した後に同じファイルの中にcondaでinstallしたgraphivizのファイルをまるごとcopyする.そして,pygraphvizのソースコードをいじって直接そのファイルを探索するようにする.
問題が起きるのは,pygraphvizのagraph.py というコードの_which 関数の部分だ.
def _which(self, name):
"""Searches for name in exec path and returns full path"""
import os
import glob
paths = os.environ["PATH"]
print("env variables : ",paths)
print("name : ", name)
if os.name == "nt":
exe = ".exe"
else:
exe = ""
for path in paths.split(os.pathsep):
match = glob.glob(os.path.join(path, name + exe))
if match:
return match[0]
raise ValueError("No prog %s in path." % name)
この関数は,環境変数を読み取ってそこから,実行に必要なファイルを見つけ出す.(ex. fdp.exe, neato.exe など)
そこで,直接,そのファイルを見つけ出すように,コードを以下のように書き足す.14-22行目が該当箇所.
def _which(self, name):
"""Searches for name in exec path and returns full path"""
import os
import glob
paths = os.environ["PATH"]
print("env variables : ",paths)
print("name : ", name)
if os.name == "nt":
exe = ".exe"
else:
exe = ""
cwd = os.getcwd()
base_dir = glob.glob(os.path.join(cwd,"graphviz*","Library"))[0]
base_path = os.path.join(base_dir,"bin","graphviz")
#print("base_path for fdp :" ,base_path)
if os.path.exists(base_path):
match= glob.glob(os.path.join(base_path,name+exe))
if match:
#print("suucessfully finding path.")
return( match[0])
for path in paths.split(os.pathsep):
match = glob.glob(os.path.join(path, name + exe))
if match:
return match[0]
raise ValueError("No prog %s in path." % name)
これでGUIファイルと同じ階層にpygraphviz*という名前のパッケージをおいておけば,ファイルを見つけて実行出来してくれるようになる.
———雑感(`・ω・´)———-
pyinstaller の –hidden-import オプションを使えばこんな面倒くさいことをしないで済んだ??
試してないです...

コメント