PythonスクリプトをPyInstallerで実行モジュール化するときに出てきた問題点
PyInstallerを使って、Pythonスクリプトをバイナリに固める。固めたバイナリを実行すると、ファイルパスの問題でうまく動かないときがある。どのような場合に動かないかを、まずは示す。
ファイル構成は下記の通り。ソースがexample.py、ソースが読み込んでいる画像ファイルがディレクトリpicsの中にある。
$ pwd /home/hoge/Python/Installer $ ls example.py pics/ $ ls pics flower.png
スクリプトexample.pyは、ウィンドウを表示するだけの簡単なもの。内容は以下の通り。
#!/bin/env python # program : example.py import os import wx class MyApp(wx.PySimpleApp): def OnInit(self): self.frm = wx.Frame(None, -1, 'Title', size=(300,200)) self.p = p = wx.Panel(self.frm, -1) dpath = os.path.dirname(__file__) ppath = os.path.join(dpath, 'pics', 'flower.png') print 'using a file: ',ppath bmp = wx.Image(ppath).ConvertToBitmap() self.frm.Show() return True app = MyApp() app.MainLoop()
実行してみよう。どんなウィンドウが表示されるかは、ここではあまり問題ではない。問題は、画像ファイルのパスppathが正しいかどうか。正しくないと、ConvertToBitmap()に失敗してエラー終了する。
スクリプトファイルがあるディレクトリからスクリプトを実行する場合
$ cd /home/hoge/Python/Installer $ python example.py using a file: pics/flower.png
ウィンドウは問題なく表示され、「using a file: ...」で画像ファイルのパスも表示される。つまり、問題なし。
スクリプトファイルがあるディレクトリとは別のディレクトリから、スクリプトを実行する場合
$ cd /home/hoge/ $ python Python/Installer/example.py using a file: Python/Installer/pics/flower.png
この場合も問題なし。
プログラムをスクリプトのまま実行するときには問題ないことが分かったので、次に、スクリプトを実行モジュールに変換して試してみる。PyInstallerを使って、Linux用のバイナリファイルを作る。
PyInstallerを実行するスクリプトは、下記のようなものでいいだろう。PyInstallerは既にインストールしてあり、実行環境も整えてある。
#!/bin/sh Makespec.py -a --onefile --name=example example.py Build.py example.spec cp -r pics dist
これを実行すると、実行モジュールexampleが作成される。ファイル構成は以下のようになる。
$ pwd /home/hoge/Python/Installer/dist $ ls example pics/
作成されたモジュールを起動してみよう。
実行モジュールがあるディレクトリから起動する場合
$ pwd /home/hoge/Python/Installer/dist $ ./example using a file: pics/flower.png
問題なく起動できた。
実行モジュールがあるディレクトリとは別のディレクトリから、モジュールを起動する場合
$ pwd /home/hoge $ Python/Installer/dist/example using a file: pics/flower.png Traceback (most recent call last): File "<string>", line 19, in <module> File "/home/hoge/Python/Installer/build/pyi.linux2/example/outPYZ1.pyz/wx._core", line 8081, in __init__ File "/home/hoge/Python/Installer/build/pyi.linux2/example/outPYZ1.pyz/wx._core", line 7981, in __init__ File "/home/hoge/Python/Installer/build/pyi.linux2/example/outPYZ1.pyz/wx._core", line 7555, in _BootstrapApp File "<string>", line 13, in OnInit File "/home/hoge/Python/Installer/build/pyi.linux2/example/outPYZ1.pyz/wx._core", line 3369, in ConvertToBitmap wx._core.PyAssertionError: C++ assertion "image.Ok()" failed at ../src/gtk/bitmap.cpp(444) in CreateFromImage(): invalid image
ダメ。flower.pngのファイルパスが正しく認識されていない。現在のディレクトリは、/home/hoge/であり、/home/hoge/pics/flower.pngを探そうとしてエラー終了している。