関数ディレクトリ ####################### :ref:`function-storage upload ` コマンドでアップロードする関数ディレクトリについて説明します。 基本情報 *********************** | ローカルで書いた Python コードを :ref:`function-storage upload ` コマンドでアップロードすることで、Cleanroom 内で実行することができます。 | アップロードは、ディレクトリ単位で行われます。 基本的なディレクトリ構造は以下の通りです。 .. code-block:: bash functions/ ├── handler.py # 実行する関数を記載したモジュール └── packages/ # 依存ライブラリを同梱する場合 エントリポイントについて *********************** :ref:`function-storage upload ` で関数ディレクトリをアップロードした後、 :ref:`cleanroom deploy ` コマンドの handler オプションで実行する関数(エントリポイント)を指定します。 エントリポイントは、``<モジュール名>.<関数名>`` の形式で指定します。 例えば関数ディレクトリ直下にある ``handler.py`` の ``run`` 関数を実行する場合は以下のように指定します。 .. code-block:: console apc cleanroom deploy --handler handler.run [他のオプション] エントリポイントは引数を持たない関数である必要があります。 .. _function-directory-library: ライブラリについて *********************** アップロードされた関数ディレクトリはCleanroom内にそのまま展開されます。 セキュリティ上の理由から、Cleanroom から pip サーバのような外部へのアクセスは出来ません。 そのため、必要なライブラリは全てディレクトリ内に同梱する必要があります。 import 文は必ず相対パスを使用してください。 例として、以下のようなディレクトリ構造を考えます。 ここで packages には pip などを用いて pandas と numpy がインストールされているとします。 .. code-block:: bash functions/ ├── handler.py ├── utils.py └── packages/ ├── pandas └── numpy この場合、``handler.py`` からは以下のようにライブラリをimportすることができます。 .. code-block:: python # handler.py import sys sys.path.append("packages") import pandas as pd import numpy as np from utils import load_data .. warning:: 必要なライブラリが関数ディレクトリ内にインストールされていない場合、handler の実行時に以下のようなエラーが発生します。 .. code-block:: console $ apc cleanroom run app --profile acompany 2025-08-07 12:50:16 [INFO]: Work status: error. Message: Failed to import module 'handler': Either the module is missing from the function directory, or it has missing dependencies. ライブラリインストール時の注意 ======================= 以下の環境に合わせたライブラリをインストールする必要があります。 - Ubuntu 22.04 - Python 3.10 - GPU非搭載 .. warning:: 環境非対応のライブラリをアップロードした場合の挙動は保証外です。 Cleanroom内で環境非対応のライブラリを呼び出した場合、以下のようなエラーが発生することが確認されています。 - ``ImportError`` - ``NameError`` - ``OSError`` - ``ValueError`` 以下は Python3.10 の Linux x86_64 用ライブラリをインストールする場合の pip コマンドの例です。 .. code-block:: console pip install \ --platform manylinux2014_x86_64 \ --only-binary=:all: \ --python-version 3.10 \ -r \ --target= .. admonition:: 例 ``requirements.txt`` に記載されたライブラリを ``./function/packages`` にインストールする場合 .. code-block:: console pip install \ --platform manylinux2014_x86_64 \ --only-binary=:all: \ --python-version 3.10 \ -r requirements.txt \ --target=./function/packages 入力ファイルのパスについて *********************** :ref:`cleanroom data cp ` コマンドでアップロードされる入力データディレクトリは、Cleanroom 内部の ``/WORK/inputs/`` に展開されます。 例えば、``./input/input.txt`` というファイルを以下のコマンドでアップロードした場合、Cleanroom 内部の ``/WORK/inputs/input_1/input.txt`` に展開されます。 .. code-block:: console apc cleanroom data cp ./input app:input_1/ したがって、handler.py では以下のようにファイルを読み込むことができます。 .. code-block:: python with open("/WORK/inputs/input_1/input.txt", "r") as f: data = f.read() 出力ファイルのパスについて *********************** :ref:`cleanroom data cp ` コマンドでダウンロードするデータは必ず `/WORK/outputs/` に書き込む必要があります。 例えば、handler.py で以下のようにファイルを書き込んだ場合、cleanroom 内部の ``/WORK/outputs/output_1/output.txt`` に書き込まれます。 .. code-block:: python with open("/WORK/outputs/output_1/output.txt", "w") as f: f.write("Hello, World!") この場合、以下のコマンドを実行することで ``./output/output.txt`` にデータをダウンロードすることができます。 .. code-block:: console apc cleanroom data cp app:output_1 ./output .. _log-output: ログ出力について *********************** :ref:`cleanroom data cp ` コマンドでダウンロードする以外の方法で、実行環境内のデータを取得することはできません。 そのため、Cleanroom実行時にログを出力する場合も、``/WORK/outputs/`` に書き込む必要があります。 現在は、ログ出力の取得は関数の実行後にのみ行えますが、今後は関数の実行中にもログ出力を取得できるようになる予定です。 特に、Cleanroom実行時に標準出力(stdout)や標準エラー出力(stderr)に出力した内容は、全て削除されることに注意してください。 エラー時の log がないとデバッグが難しいため、実行関数に try-except を使用するなどして、適切にエラーをキャッチして ``/WORK/outputs/`` に出力することを推奨します。 .. warning:: ログ出力に入力データの内容を含めてしまうと、入力データの漏洩に繋がる可能性があります。 特に **traceback には意図せずデータの内容が入っていることがある** ため、traceback の内容をログに出力する場合は十分注意してください。 ログに出力する内容を入力データに依存しない形式にすることを強く推奨します。 以下はキャッチしたエラーから、その型と発生した場所のみを保存するようなスクリプトの例です。 エラーの型と発生した場所のみをログに出力することで、入力データの内容を漏洩させることなく、エラーの原因を特定することができます。 .. code-block:: python import traceback def run(): try: # 実行したい処理 except BaseException as e: # エラーの型をログに出力 error_log = f"error type: {type(e).__name__}\n" # エラーの発生した場所をログに出力 tb = traceback.extract_tb(e.__traceback__) if tb: for i, frame in enumerate(tb): error_log += f"error location {i + 1}: {frame.filename}:{frame.lineno}\n" with open("/WORK/outputs/output_1/error.txt", "w") as f: f.write(error_log) 使用メモリについて *********************** 関数の実行に使用できるメモリ量は、 :ref:`cleanroom deploy ` コマンドの ``--memory`` オプションで指定します。 指定したメモリ以上のメモリを使用すると、 ``MemoryError`` が発生します。 MemoryError は気づきにくく、エラーメッセージが存在しないケースもあります。 :ref:`ログ出力について` の例のようにエラーの型を出力したり、MemoryError を個別にキャッチするなどの工夫をすることを推奨します。 マルチプロセスについて *********************** APC-DCR では、関数の実行にマルチプロセスを使用することはできません。 マルチプロセスを用いるコードを実行した場合、 ``BlockingIOError`` が発生します。