Python スクリプトのスタンドアロン化【bbfreeze】
関連記事
Pythonスクリプトのスタンドアロン化
上記の記事で、Pythonのスクリプトを cx_Freeze というライブラリを用いてスタンドアロン化する方法を紹介しました。(「スタンドアロン化」については上記記事参照)
最近、cx_Freeze よりも bbfreeze というライブラリを用いた方が楽にスタンドアロン化できることに気づいたので、その方法を紹介します。
bbfreeze の利点
bbfreeze · PyPIcx_Freeze と比較した bbfreeze の利点は主に以下の2点です。
- setup.py ファイルを書くのが簡単
- フリーズされたバイナリファイルが軽い(比較的)
cx_Freeze では setup.py ファイルに使用するライブラリや依存するバイナリファイルを手書きで指定してやる必要がありましたが、bbfreeze ではそれらは必要なく自動でかき集めてくれるようです。
bbfreeze の使い方
bbfreeze の使い方は cx_Freeze とほぼ同じで、
みたいな感じです。
例えば、以下のコードをフリーズすることを考えます。
sample.py
from scipy import dot, rand print dot(rand(10, 1), rand(1, 10))
setup.py は次のように書けます。
setup.py
from bbfreeze import Freezer f = Freezer("./build/",includes=()) f.addScript("sample.py" , True) f()
これだけです。フリーズされたバイナリファイルの置き場所とフリーズするメインスクリプトを指定しています。
python setup.py
を実行することで、"./build/sample" としてスタンドアロン化することができます。
bbfreeze の注意点
glibc のバージョン
bbfreeze の公式サイトにさりげなく次のように書かれています。
Linux Notes
https://pypi.python.org/pypi/bbfreeze
The glibc version on the system used for freezing will generally be the minimum glibc version required to run the binaries.
フリーズしたバイナリファイルを実行する環境の glibc のバージョンが、フリーズする環境の glibc 以上である必要があります。よって linux ディストリビューションでスタンドアロン化を行う場合は、できるだけ glibc のバージョンが低い OS で行うべきです。
例えば、"Ubuntu 12.04" でフリーズしたバイナリファイルは "Ubuntu 14.04" で実行することができますが、その逆は不可となります。
bbfreeze で対処すべき点
上で扱ったコードのようにあまりライブラリを使わないシンプルなものは上手くフリーズできる場合が多いですが、使用するライブラリによってフリーズが失敗する場合があります。それらを回避するための方法を紹介しておきます。
bbfreeze/recipe.py の変更
bbfreeze ライブラリ内の、recipe.py というファイル内に "mf.import_hook("matplotlib.numerix.random_array", m)" という行が存在します。しかし、最新の matplotlib では numerix というモジュールは存在しないため、場合によってはこの行でエラーがでてしまいます。これに対処するには、この行をコメントアウトすれば十分です。
もしコメントアウトに伴って何かエラーが発生した場合は...頑張ってください。
bbfreeze/freezer.py の変更
bbfreeze ライブラリ内の、freeze.py というファイル内に "replace_paths_in_code()" という関数があります。この関数は返り値の一つとして "newname" という文字列を持ちますが、これが文字コードエラーを引き起こす場合がありました。以下のように変更してしまいましょう。
newname -> str(newname)
足りない関数の補填
bbfreeze は使用するライブラリ関数などを自動でかき集めてフリーズしてくれますが、たまに取りこぼしがあるようです。例えば、自分の場合はフリーズしたバイナリファイルを実行した際、以下の関数がインポートできないとエラーがでたため、元のメインスクリプトに明示的にインポート文を書き足すことで対処できました。
import scipy.special._ufunc_cxx import scipy.sparse.csgraph._validation