MaxCompute では、Python ユーザー定義関数 (UDF) 内で NumPy パッケージやコンパイルが必要なパッケージ、ダイナミックリンクライブラリに依存するサードパーティ製パッケージなど、サードパーティ製パッケージを使用できます。本トピックでは、それらの使用方法を説明します。
背景情報
Python UDF でサードパーティ製パッケージを使用できるシナリオは次のとおりです。
NumPy パッケージのファイル名拡張子を変更し、MaxCompute クライアントを使用してパッケージをアップロードした後、関数を登録します。その後、Python 3 UDF からその関数を呼び出せます。
MaxCompute と互換性のある環境で、サードパーティ製パッケージ内の setup.py スクリプトをコンパイルして WHL パッケージを生成し、パッケージのファイル名拡張子を変更します。その後、MaxCompute クライアントを使用してパッケージをアップロードし、関数を登録します。その後、Python UDF からその関数を呼び出せます。
ダイナミックリンクライブラリに依存するサードパーティ製パッケージの使用
サードパーティ製パッケージのソースコードから .so ライブラリファイルをコンパイルし、WHL パッケージを生成した後、パッケージのファイル名拡張子を変更します。その後、MaxCompute クライアントを使用してパッケージおよび .so ライブラリファイルをアップロードし、関数を登録します。その後、Python UDF からその関数を呼び出せます。
前提条件
作業を開始する前に、次の要件を満たしていることを確認してください。
Python がインストールされていること。Python 3 を推奨します。
MaxCompute クライアント がインストールおよび設定済みであること。詳細については、「MaxCompute クライアントのインストールおよび設定」をご参照ください。
コンパイルが必要なパッケージについては、pip、setuptools、および wheel がインストールされていることを確認してください。setuptools をインストールするには
pip install setuptoolsコマンドを実行し、wheel をインストールするにはpip install wheelコマンドを実行できます。GDAL 3.0 以降を使用する場合は、PROJ 6 がインストールされていること。
Docker を使用してサードパーティ製パッケージをコンパイルする場合は、Docker がインストールされていること。詳細については、Docker インストールドキュメント をご参照ください。
NumPy パッケージの使用 (Python 3 UDF)
MaxCompute の Python 2 環境にはデフォルトで NumPy が含まれています。Python 3 UDF で NumPy パッケージを使用するには、次の手順に従ってパッケージを手動でアップロードする必要があります。
バージョン 1.19.2 を例として、PyPI ページにアクセスします。Download files セクションで、ファイル名が cp37-cp37m-manylinux1_x86_64.whl で終わる NumPy パッケージをダウンロードします。
説明ファイル名拡張子が異なるパッケージを使用すると、ロードが失敗する可能性があります。別のバージョンを使用する場合は、PyPI ページの左上隅にある Navigation セクションで Release history をクリックし、過去のバージョンを確認してください。
ダウンロードした NumPy パッケージのファイル名拡張子を .zip に変更します。
例: numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip。
MaxCompute クライアント を使用して、NumPy パッケージを MaxCompute プロジェクトにアップロードします。リソースのアップロード方法の詳細については、「リソース操作」をご参照ください。
サンプルコマンド:
ADD ARCHIVE D:\Downloads\numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip -f;Python UDF スクリプトを作成し、.py ファイルとして保存します。
以下は import_numpy.py として保存された Python UDF スクリプトのサンプルです。
from odps.udf import annotate @annotate("->string") class TryImport(object): # クラス名は TryImport です。 def __init__(self): import sys sys.path.insert(0, 'work/numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip') # NumPy パッケージ。work/ 以降のパッケージ名のみ置き換えてください。 def evaluate(self): import numpy return "import succeed"MaxCompute クライアント を使用して、import_numpy.py スクリプトをリソースとして MaxCompute プロジェクトにアップロードします。
サンプルコマンド:
ADD PY D:\Desktop\import_numpy.py -f;アップロードした import_numpy.py スクリプトおよび NumPy パッケージを使用して、MaxCompute クライアント を通じてユーザー定義関数を登録します。関数の登録方法の詳細については、「関数操作」をご参照ください。
登録するユーザー定義関数の名前を numpy とし、関数リソースが test_project プロジェクト内にあると仮定します。サンプルコマンド:
CREATE FUNCTION numpy AS 'import_numpy.TryImport' USING 'test_project/resources/import_numpy.py,numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip';説明関数を登録する際は、numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip のような NumPy パッケージをリソースリストに追加する必要があります。
関数を登録したら、SQL ステートメントから呼び出します。実行時に Python 3 を有効にしてください。詳細については、「Python 3 UDF 開発仕様およびワークフロー」をご参照ください。
コンパイルが必要なパッケージの使用
サードパーティ製パッケージが PyPI からの TAR.GZ アーカイブまたは GitHub からのソースコードパッケージである場合、解凍後のパッケージのルートディレクトリに setup.py ファイルが含まれている可能性があります。このタイプのパッケージを使用するには、まず MaxCompute と互換性のある環境で setup.py ファイルをコンパイルして WHL パッケージを生成する必要があります。その後、リソースをアップロードし、関数を登録します。これにより、Python UDF を使用してサードパーティ製パッケージを呼び出せます。リソースのアップロードおよび関数の登録に関する詳細については、「NumPy パッケージの使用 (Python 3 UDF)」をご参照ください。
サードパーティ製パッケージは MaxCompute 上の Linux 環境で実行されます。互換性の問題を回避するため、Windows ではなく Linux 環境でコンパイルすることを推奨します。
Windows 環境を使用する場合は、対応するバージョンの Python (
/opt/python/cp27-cp27m/bin/pythonまたは/opt/python/cp37-cp37m/bin/python3) を使用して、quay.io/pypa/manylinux2010_x86_64Docker コンテナ内で WHL パッケージをビルドすることを推奨します。
Linux 環境を使用する場合は、次のポイントを確認して互換性を確保してください。
互換性のある Python バージョンを使用する必要があります。システムのコマンドラインインターフェイス (CLI) で次のコマンドを実行し、Python バージョンの互換性を確認します。
python -c "import wheel.pep425tags; print(wheel.pep425tags.get_abi_tag())"cp27mまたはcp37mが返された場合、Python バージョンは互換性要件を満たしています。cp27muまたはcp37muが返された場合、Python バージョンは互換性要件を満たしていません。CLI で./configure --enable-unicode=ucs2コマンドを実行し、Python のエンコーディングを UCS-2 に設定する必要があります。
C または C++ コードに依存する場合は、互換性のある GNU Compiler Collection (GCC) バージョンを使用する必要があります。
説明GCC 4.9.2 以前のバージョンを使用することを推奨します。GCC 4.9.2 より新しいバージョンを使用すると、生成された WHL パッケージ内の .so ファイルが MaxCompute 環境と互換性を持たない可能性があります。
環境が互換性要件を満たしたら、次の手順に従って setup.py ファイルから WHL パッケージを生成します。
サードパーティ製パッケージをローカルディレクトリに展開します。システムの CLI で、setup.py ファイルがあるフォルダに切り替えます。
たとえば、GDAL-3.2.0.zip パッケージをダウンロードして展開した場合、setup.py ファイルは D:\Downloads\GDAL-3.2.0 ディレクトリ内にあります。サンプルコマンド:
cd D:\Downloads\GDAL-3.2.0CLI で次のコマンドを実行し、出力に bdist_wheel が含まれているか確認します。
サンプルコマンド:
python setup.py --help-commandCLI で次のコマンドを実行し、コンパイルして WHL パッケージを生成します。
python setup.py bdist_wheel説明WHL パッケージは dist ディレクトリ内に生成されます。
ダイナミックリンクライブラリを持つパッケージの使用
一部のサードパーティ製 Python パッケージは、Python ライブラリに加えて他のダイナミックリンクライブラリにも依存する場合があります。本セクションでは、GDAL 3.0.4 を例として、quay.io/pypa/manylinux2010_x86_64 Docker コンテナを使用して関連する .so ライブラリファイルをコンパイルし、MaxCompute で使用可能な WHL パッケージを生成する方法を説明します。生成されたファイルを使用してリソースをアップロードし、関数を登録することで、Python UDF からパッケージを呼び出せます。リソースのアップロードおよび関数の登録に関する詳細については、「NumPy パッケージの使用 (Python 3 UDF)」をご参照ください。
作業を開始する前に Docker がインストールされていることを確認してください。Docker 操作の詳細については、Docker ドキュメント をご参照ください。
Python UDF で .so ライブラリファイルに依存するサードパーティ製パッケージを使用するには、次の手順に従います。
依存関係を確認します。PyPI ページの Dependencies セクションで依存関係を確認できます。
たとえば、GDAL 3.0.4 の依存関係は次のとおりです。
Dependencies - libgdal (3.0.4 以上) およびヘッダーファイル (gdal-devel) - numpy (1.0.0 以上) およびヘッダーファイル (numpy-devel) (明示的には必須ではありませんが、多くの例およびユーティリティはこれなしでは動作しません)説明上記のように、依存関係には libgdal および numpy が含まれます。libgdal はコンテナ内で GDAL ソースコードをコンパイルすることで取得し、numpy は PyPI ページから NumPy パッケージをダウンロードするか、Docker コンテナ内で取得します。
NumPy パッケージをダウンロードします。
NumPy パッケージは次のいずれかの方法でダウンロードできます。
PyPI ページの Download files セクションで、ファイル名が cp37-cp37m-manylinux1_x86_64.whl で終わる NumPy パッケージをダウンロードします。
説明Python 2 環境を使用する場合は、互換性のある NumPy パッケージをダウンロードする必要があります。PyPI ページの左側の Navigation エリアで Release history をクリックし、バージョン 1.16.6 以前を選択して、ファイル名が cp27-cp27m-manylinux1_x86_64.whl で終わるパッケージをダウンロードします。
quay.io/pypa/manylinux2010_x86_64 Docker コンテナ内で、
/opt/python/cp37-cp37m/bin/pip download numpy -d ./コマンドを実行して、現在のディレクトリに NumPy パッケージをダウンロードします。
.so ライブラリファイルをコンパイルします。
GDAL 3.0.4 ソースコード をダウンロードし、ローカルディレクトリに展開します。
Docker を使用して quay.io/pypa/manylinux2010_x86_64 コンテナイメージをプルし、インタラクティブ端末モードに入ります。
サンプルコマンド:
docker pull quay.io/pypa/manylinux2010_x86_64 docker run -it quay.io/pypa/manylinux2010_x86_64 /bin/bashGDAL 3.0.4 ソースコードをコンテナにコピーします。
サンプルコマンド:
docker cp ./gdal-3.0.4 <CONTAINER ID>:/opt/source/CONTAINER ID の取得方法については、docker ps をご参照ください。
コンテナ内で GDAL 3.0.4 をコンパイルします。詳細については、BuildingOnUnix をご参照ください。
サンプルコマンド:
# PROJ 6 のインストールディレクトリを configure オプションで指定する必要があります。 ./configure --prefix=/path/to/install/prefix --with-proj=/path/to/install/proj6/prefix make make install export PATH=/path/to/install/prefix/bin:$PATH export LD_LIBRARY_PATH=/path/to/install/prefix/lib:$LD_LIBRARY_PATH export GDAL_DATA=/path/to/install/prefix/share/gdal # テスト gdalinfo --versionコンパイル中に次のエラーが発生する可能性があります。
configure: error: PROJ 6 symbols not found:GDAL 3.0 以降のバージョンは PROJ 6 に依存します。PROJ 6 をダウンロードしてインストールする必要があります。fatal error: zlib.h: No such file or directory:yum install zlib-develコマンドを実行してから、再度コンパイルします。
docker cp コマンドを使用して、libgdal.so および libproj.so ファイルをコンテナからローカルマシンにコピーします。これらのファイルはそれぞれのインストールディレクトリの lib フォルダ内にあります。シンボリックリンクではなく、実際のファイルをコピーすることを確認してください。
コンテナ内で GDAL WHL パッケージを作成します。詳細については、BuildingOnUnix をご参照ください。
サンプルコマンド:
# NumPy が必要な場合は、事前に NumPy をインストールする必要があります。 /opt/python/cp37-cp37m/bin/pip install numpy # GDAL ソースコードのディレクトリに切り替えます。 cd swig/python # dist ディレクトリ内に WHL パッケージが生成されます。例:GDAL-3.0.4-cp37-cp37m-linux_x86_64.whl /opt/python/cp37-cp37m/bin/python setup.py bdist_wheel生成された .so ライブラリファイル、WHL パッケージ、または NumPy パッケージに基づいて、リソースをアップロードし、関数を登録して、Python UDF でサードパーティ製パッケージを使用します。リソースのアップロードおよび関数の登録に関する詳細については、「NumPy パッケージの使用 (Python 3 UDF)」をご参照ください。
次の点に注意してください。
リソースをアップロードする際は、libgdal.so および libproj.so を FILE リソースとしてアップロードし、numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip および GDAL-3.0.4-cp37-cp37m-linux_x86_64.zip を ARCHIVE リソースとしてアップロードする必要があります。
関数を登録する際は、libgdal.so、libproj.so、numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip、および GDAL-3.0.4-cp37-cp37m-linux_x86_64.zip を関数のリソースリストに追加する必要があります。
以下は Python UDF のサンプルコードです。
説明この例は Python 3 コードを使用しており、Python 3 環境で実行する必要があります。Python 2 環境で実行する必要がある場合は、
get_cache_fileパラメーターの使用方法に注意してください。詳細については、「リソースの参照」をご参照ください。# coding: utf-8 from odps.udf import annotate from odps.distcache import get_cache_file def include_file(file_name): import os, sys so_file = get_cache_file(file_name, 'b') with open(so_file.name, 'rb') as fp: content=fp.read() so = open(file_name, "wb") so.write(content) so.flush() so.close() @annotate("->string") class TryImport(object): def __init__(self): import sys include_file('libgdal.so.26') include_file('libproj.so.15') sys.path.insert(0, 'work/GDAL-3.0.4-cp37-cp37m-linux_x86_64.zip') # コンパイル済みの GDAL パッケージ。work/ 以降のパッケージ名のみ置き換えてください。 sys.path.insert(0, 'work/numpy-1.19.2-cp37-cp37m-manylinux1_x86_64.zip') # NumPy パッケージ。work/ 以降のパッケージ名のみ置き換えてください。 def evaluate(self): from osgeo import gdal from osgeo import ogr from osgeo import osr from osgeo import gdal_array from osgeo import gdalconst return "import succeed"説明libgdal.so.26 または libproj.so.15 が見つからないという実行時エラーが発生した場合は、アップロードした libgdal.so および libproj.so ファイルをそれぞれ libgdal.so.26 および libproj.so.15 にリネームしてください。