Pythonスクリプト/スクリプトに使用しているサードパーティPythonモジュール群をzipファイル化して配布する方法を紹介します。
背景
pip経由で取得したサードパーティPythonモジュールを活用したPythonツール/スクリプトを配布するときに以下のように困った状況に陥ることがあります。
- ツールを使用するマシンではpipコマンドを使用できないため、Pythonモジュールをインストールできない。
- ツールを使用するマシンではDockerを使用できないため、PythonモジュールをDockerコンテナに同梱して配布できない。
Pythonは標準ライブラリが非常に充実しているため、ちょっと我慢して諦めてしまう人を結構見かけます。しかし上記の理由で「Pythonモジュールを使えば実装する時間を大幅に短縮できる」という選択肢を放棄するのは勿体なすぎます。
選択肢を放棄しないための手段の一つとして、本記事では**Pythonモジュール群のzipファイルを作成し、これをPythonモジュールとしてimportする
**手順を紹介します。
手順
ここでは個人的にPythonスクリプトを作成する時によく利用するdocker, clickという2つのPythonモジュール(および依存関係)のzipファイルを作成してimportする手順を例として示します。
NOTE: コマンドラインインタフェース(CLI)を持つツールを簡単に作りたい場合、clickはとてもお勧めなので是非とも利用してください
zipファイルを作成
以下の手順で必要なPythonモジュール群のzipファイルを作成します。C言語モジュールが含まれている場合、作成したzipファイルはOS/プラットフォーム依存のものとなるため注意が必要です。
なおpipコマンドでPythonモジュール群を収集する手順については、requirements.txt
等がある場合はそれを指定するようにしてください。
# 1. Pythonモジュール群を格納するディレクトリ作成
mkdir my-py-library
# 2. Pythonモジュール群をpip経由で収集
# -> この例ではdocker, clickを依存関係含めて収集
pip3 install docker click -t my-py-library
# 3. C言語モジュールがないかチェック
# -> 存在する場合は、OS/プラットフォーム依存となる
find my-py-library | egrep '\.so$|\.pyd$'
# 4. Pythonモジュール群のzip化
cd my-py-library
zip -r ../my-py-library.zip *
cd ..
これで上記の例ではmy-py-library.zip
というzipファイルが作成されます。これを次の手順でimportすることにより、このzipファイルに含まれているclick, dockerモジュールを利用できます。
zipファイルをimport
Pythonスクリプトと同じディレクトリにzipファイルが配置されている場合、以下のようにimportします。
-
sys.path.insert(0, <zipファイルパス>)
でzipファイルをPYTHONPATHとして追加する-
os.path.realpath(__file__)
を使用することで、Pythonスクリプトの絶対パスを取得できる。この絶対パスを用いてzipファイルのパスを指定する。
-
- PYTHONPATHを追加した後、必要なPythonモジュールをimportする。
なお、下記例のようにPYTHONPATHを設定した場合、どこからPythonスクリプトを実行した場合でもPythonスクリプトと同じディレクトリのzipファイルを参照されます。Pythonスクリプトとzipファイルをセットで配布する場合は、このようにPYTHONPATHを設定した方が色々と都合が良いです。
import os
import sys
# PYTHONPATHにzipファイルを追加
basepath = os.path.split(os.path.realpath(__file__))[0]
sys.path.insert(0, os.path.join(basepath, 'my-py-library.zip'))
# zipファイルに含まれるPythonモジュールをimport
import click
import docker
# Do something...
import文の箇所でエラーが発生しなければ正常にimportされています。
補足
-
zipファイルではなくディレクトリでも利用できます。zipにしているのは以下の利点があるためです。やや特殊な開発、運用ルールがあるところでは意外と重宝します。
- 配布が容易である
- バージョン管理システムでソースコードとして管理する必要がない
-
C言語モジュールが含まれる場合、動作環境がOS、CPUアーキテクチャ、Pythonバージョンに依存するようになります。また内部で特定環境(ex. Linux, mac OS)のコマンドを実行していたり、ライブラリにアクセスなどをしている場合はC言語モジュールが含まれていない場合でも同様です。
-
ここで紹介した手順はPython2/3の両バージョンで利用できます。
- Python2.3で導入された
zipimport
を使用した仕組みのため、基本的にPython2.3以上であれば利用可能。
- Python2.3で導入された