Python スクリプトのスタンドアロン化
自分がググり倒した成果を書き連ねています。
この記事では、主にLinux環境を前提としているので注意してください。
WindowsやMacでも同じような感じでいけるかも知れないです。
スタンドアロン アプリケーション
Pythonはスクリプト言語であるため、インタプリタがインストールされている環境でしかプログラムを実行することができません。さらに、プログラムに外部パッケージ(Numpy、Scipyなど)を使用している場合は、それらのインストールも必要となります。一方、C++やJavaなどのコンパイル言語では、ソースコードをバイナリコードへコンパイルするため、大体どのような環境でも動かすことが可能です。
しかし、Pythonをメインで使っているプログラマとしては、Pythonのコードもどのような環境でも動くスタンドアロンアプリケーションに変換したいなあ、と思うわけです。そうすれば、相手の環境を気にすることなく、自分の書いたアルゴリズムなどを配布することができます。
今回は特に、信号処理でよく用いられるNumpy、Scipyなどの外部ライブラリを含んだコードをスタンドアロンにする方法を、備忘録的に書いておこうと思います。
cx_Freezeによるスタンドアロン化
Pythonコードをスタンドアロンにするためのツールはいくつかあるようですが、今回はcx_Freezeというものを用いた方法を紹介します。(自分がうまくいったから)cx_FreezeはPythonの外部パッケージなので、インストールは簡単にできます。面倒くさいのでググってください。
cx_Freezeがやってることは(多分)、プログラムの中で使ってるライブラリとかを全部かき集めてきてバイナリでラッピングするみたいな感じだと思います。(詳しくは知らない)
sample code
今回は SciPy などを使ったコードをスタンドアロン化することが目的なので、以下のようなコードを例にします。
from scipy import rand print rand()
setup.py を書こう!
こんな感じで書きます。
# coding: utf-8 # Setup file for cx_Freeze import sys from cx_Freeze import setup, Executable # ------- # Setup # ------- packages = [] includes = ["scipy"] excludes = [] binpaths = ["/usr/lib/atlas-base/", "/usr/lib/"] binincludes = ['/usr/lib/libatlas.so.3gf', '/usr/lib/liblapack.so.3gf', '/usr/lib/libblas.so.3gf'] init_script = "ConsoleSetLibPath" base = None # if sys.platform == 'win32' : base = 'Win32GUI' # exe にしたい python ファイルを指定 exe = Executable(script = './test.py', base = base) # セットアップ setup(name = 'test', version = '0.2', description = 'converter', options = {"build_exe": {'copy_dependent_files':True, "includes":includes, "excludes":excludes, "packages":packages, 'bin_path_includes':binpaths, 'bin_includes':binincludes, 'create_shared_zip':True, "init_script": init_script}}, executables = [exe])
上のsetupファイルで重要な部分を説明します。
- packages: 使うパッケージを列挙
- includes: 使うモジュールを列挙
- binpaths: 依存するバイナリファイルのディレクトリ
- binincludes: 依存するバイナリファイルのパス
scipyなどは、"packages" と "includes" のどちらに書いても動きますが、"packages" は余計なものまで色々フリーズしてしまい容量が大きくなるので、"includes" のほうがいいと思います。
"binincludes" はかなり重要で、最初一番ハマったところです。
scipyなどで使っているatlas、lapack、blasといった計算ライブラリのパスを指定しています。もちろん環境によってパスが違ったりすると思うので、その辺は頑張って調べてください。(これは Ubuntu12.04 環境)
実はこれを記述しなくても、パッケージングしたマシンでは多分動きますが、他のマシンにファイルを移して実行するとエラーがでる、と言ったことが起きます。