exxoで1ファイルバイナリを作ろう
exxo というツールを使ってPythonアプリケーションを 1ファイルの実行バイナリにパックして簡単に配布できるようにしてみよう!
ターゲット環境
現在のアウトプットが動作する環境は以下のみです。
- Linux amd64
ビルドに必要な環境と依存パッケージ
以下の通りですが、 dockerを利用することでさらに広範囲の環境でビルドすることもできます。
- Linux amd64
- Python3.4系またはPython2.7系のどちらか
- UPX(オプショナル)
インストール
exxo 自身が1ファイルバイナリとしてビルド済みのものがダウンロードできます。
curl -L https://bintray.com/artifact/download/mbachry/exxo/exxo-0.0.5.tar.xz | tar xJvf - -C /usr/local/bin
最後のパスは$HOME/binなどPATH環境変数に列挙されたパスならどこでも構いません。
exxo の使い方
virtualenv環境準備
for Python3.4
exxo venv /tmp/myenv
source /tmp/myenv/bin/activate
for Python2.7
exxo venv -p 2.7 /tmp/myenv
source /tmp/myenv/bin/activate
注釈
この時、exxoはvirtualenv環境上にあるパッチを当てています。 なので通常のvirtualenvで作った環境は使えません。
コードのフォルダ構成
以下のようにファイルツリーを構築します。
- setup.py
- pkg/
- __init__.py (空ファイル)
- sample.py
setup.py
import os
from setuptools import setup, find_packages
VERSION='0.1.0'
ROOT = os.path.realpath(os.path.dirname(__file__))
install_requires = [
'pytz>=2015.7',
]
setup(
name='sample',
version=VERSION,
author='accense',
author_email='sample@sample.org',
url='http://sample.org',
description='sample application.',
long_description='''sample''',
packages=find_packages(),
zip_safe=False,
install_requires=install_requires,
extras_require={},
include_package_data=True,
entry_points={
'console_scripts': [
'main = pkg.sample:main',
],
},
)
sample.py
def main():
print('hello world!')
ビルド
setup.pyのあるフォルダにて
exxo build
以上でsetup.pyにてビルド後、virtualenv環境に投入されたパッケージや バンドル指定をしたパッケージやその他のファイル群をzip圧縮したものを 起動用バイナリのリソースにくっつけた1ファイル実行ファイルを出力します。
exxo のパッチの仕組み
パッケージパスを参照するファイルアクセスをzipリソースに振り向ける仕組み。 zipに含まれるパスを参照するとzip内容を読み出す。 それ以外の読み書きは実際のファイルにアクセスする。
トラブルシューティング
以外とハマりやすいのが必要なファイルがバンドルされていないパターン。
確認方法は
(myenv)> python setup.py sdist
と実行するとtarアーカイブが出力されます。そのtarに必要なファイルが揃っているか よく確認しましょう。ここに入っていないコードやデータは 1ファイルバイナリには含まれていませんので ファイルが見つからないエラーが出ます。
また、Djangoを使う場合2つ注意点があります。
- templates配下がパッケージングされるようにする(MANIFEST.inを書くのが簡単)
- 「manage.py runserver」以外のサーバーを使う場合はstaticファイルサーブをお忘れなく (「manage.py collectstatic」してそのフォルダをMANIFEST.inに加えるのがオススメ。)
Djangoサンプル
https://github.com/nobonobo/1binary-sample
dockerベースでビルドするようにしてあるので、 nativeのdockerまたはdocker−machineのある環境でもビルドできます。 (実行はdocker内でしかできないかも。)
まとめ
golang+go-bindataみたいに1ファイルでアプリケーションが動きますー。
成果物は1ファイルだけで対象にインストール可能なのでデプロイ作業が簡単です。 ただ、デバッグはちょとやりにくくなるかもねー。