この記事では,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 オプションを使えばこんな面倒くさいことをしないで済んだ??
試してないです...
コメント