pyinstallerでpygraphvizをGUI化して使えるようにする.

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

コメント

タイトルとURLをコピーしました