Python の Lambda 関数ハンドラーの定義
Lambda 関数ハンドラーは、イベントを処理する関数コード内のメソッドです。関数が呼び出されると、Lambda はハンドラーメソッドを実行します。関数は、ハンドラーが応答を返すか、終了するか、タイムアウトするまで実行されます。
Python で関数ハンドラーを作成するときは、次の一般的な構文が使用できます。
def
handler_name
(event, context): ... returnsome_value
命名
Lambda 関数の作成時に指定される Lambda 関数ハンドラー名は、以下から取得されます。
-
Lambda ハンドラー関数が配置されているファイルの名前
-
Python ハンドラー関数の名前
関数ハンドラーには任意の名前を付けることができますが、Lambda コンソールのデフォルト名は lambda_function.lambda_handler
です。この関数ハンドラー名には、関数名 (lambda_handler
) と、ハンドラコードが保存されているファイル (lambda_function.py
) が反映されます。
異なるファイル名または関数ハンドラー名を使用してコンソールで関数を作成する場合は、デフォルトのハンドラー名を編集する必要があります。
関数ハンドラー名を変更するには (コンソール)
-
Lambda コンソールの [関数]
ページを開き、関数を選択します。 -
[コード] タブを選択します。
-
[ランタイム設定] ペインまでスクロールして、[編集] を選択します。
-
[ハンドラー] には、関数ハンドラーの新しい名前を入力します。
-
[Save] を選択します。
仕組み
Lambda が関数ハンドラーを呼び出すと、Lambda ランタイムが 2 つの引数を関数ハンドラーに渡します。
-
最初の引数は イベントオブジェクト です。イベントは、処理する Lambda 関数のデータを含む JSON 形式のドキュメントです。 Lambda ランタイム は、イベントをオブジェクトに変換し、それを関数コードに渡します。これは通常 Python
dict
タイプです。またlist
、str
、int
、float
、またはNoneType
タイプを使用できます。イベントオブジェクトには、呼び出し元のサービスからの情報が含まれます。関数を呼び出すときは、イベントの構造とコンテンツを決定します。AWS のサービスで関数を呼び出す場合、そのイベントはサービスによって定義されます。AWS サービスからのイベントの詳細については、「他の AWS サービスからのイベントを使用した Lambda の呼び出し」を参照してください。
-
2番目の引数は コンテキストオブジェクト です。コンテキストオブジェクトは、ランタイムに Lambda によって関数に渡されます。このオブジェクトは、呼び出し、関数、およびランタイム環境に関する情報を示すメソッドおよびプロパティを提供します。
値の返し
オプションで、ハンドラーは値を返すことができます。戻り値に何が起きるかは、呼び出しの種類と呼び出したサービス に応じて変わります。以下に例を示します。
-
Lambda 関数を同期的に呼び出す のような
RequestResponse
呼び出しタイプを使用すると、AWS Lambda は Python 関数の呼び出しの結果を、Lambda 関数を呼び出したクライアントに返します (呼び出しリクエストに対する HTTP レスポンスでは、JSON にシリアル化されます)。たとえば、AWS Lambda のコンソールはRequestResponse
の呼び出しタイプを使用するため、コンソールを使用して関数を呼び出すと、コンソールに戻り値が表示されます。 -
ハンドラーから
json.dumps
でシリアル化できないオブジェクトが返された場合、ランタイムはエラーを返します。 -
None
ステートメントを指定しなかった場合の Python 関数の暗黙の動作と同じように、ハンドラーがreturn
を返した場合、ランタイムはnull
を返します。 -
「
Event
」 呼び出しタイプ (非同期呼び出し) を使用する場合、値は破棄されます。
注記
Python 3.9 以降のリリースでは、Lambda はエラーの応答時に呼び出しの requestId を含めます。
例
次のセクションでは、Lambda で使用できる Python 関数の例を示します。Lambda のコンソールを使用して関数を作成する場合、このセクションで関数を実行するために .zip アーカイブファイルをアタッチする必要はありません。これらの関数は、選択した Lambda ランタイムに含まれている標準の Python ライブラリを使用します。詳細については、「デプロイパッケージ」を参照してください。
メッセージの返し
以下は、lambda_handler
と呼ばれる関数の例を示しています。この関数は、姓と名のユーザー入力を受け入れ、入力として受信したイベントからのデータを含むメッセージを返します。
def lambda_handler(event, context): message = 'Hello {} {}!'.format(event['first_name'], event['last_name']) return { 'message' : message }
次のイベントデータを使用して関数を呼び出すことができます。
{ "first_name": "John", "last_name": "Smith" }
レスポンスには、入力として渡されたイベントデータが表示されます。
{ "message": "Hello John Smith!" }
レスポンスの解析
以下は、lambda_handler
と呼ばれる関数の例を示しています。この関数は、ランタイムに Lambda によって渡されたイベントデータを使用します。JSON レスポンスで返されるAWS_REGION
の 環境変数 を解析します。
import os import json def lambda_handler(event, context): json_region = os.environ['AWS_REGION'] return { "statusCode": 200, "headers": { "Content-Type": "application/json" }, "body": json.dumps({ "Region ": json_region }) }
関数の呼び出し には、どのイベントデータでも使用できます。
{ "key1": "value1", "key2": "value2", "key3": "value3" }
Lambda ランタイムは、初期化中にいくつかの環境変数を設定します。ランタイムでレスポンスで返される環境変数の詳細については、「Lambda 環境変数を使用したコードの値の設定」を参照してください。
この例の関数は、Invoke API からの正常なレスポンス (200
からの) によって異なります。[API を呼び出す] ステータスの詳細については、「 Invoke Response Syntax」を参照してください。
計算の返し
以下は、lambda_handler
と呼ばれる関数の例を示しています。この関数はユーザー入力を受け入れ、ユーザーに計算を返します。このサンプルの詳細については、「 aws-doc-sdk-examples GitHub リポジトリ
import logging logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): ... result = None action = event.get('action') if action == 'increment': result = event.get('number', 0) + 1 logger.info('Calculated result of %s', result) else: logger.error("%s is not a valid action.", action) response = {'result': result} return response
次のイベントデータを使用して関数を呼び出すことができます。
{ "action": "increment", "number": 3 }
Python Lambda 関数のベストプラクティスに従ってください。
Lambda 関数をビルドするときは、次のリストのガイドラインに従って、コーディングのベストプラクティスを実行してください。
-
Lambda ハンドラーをコアロジックから分離します。これにより、関数の単体テストが実行しやすくなります。例えば、Python では次のようになります。
def lambda_handler(event, context): foo = event['foo'] bar = event['bar'] result = my_lambda_function(foo, bar) def my_lambda_function(foo, bar): // MyLambdaFunction logic here
-
関数のデプロイパッケージ内で依存関係を制御します。AWS Lambda 実行環境には多数のライブラリが含まれています。Node.js および Python ランタイムの場合、ライブラリには AWS SDK が含まれます。最新の機能やセキュリティ更新プログラムを有効にするために、Lambda はこれらのライブラリを定期的に更新します。この更新により、Lambda 関数の動作が微妙に変化する場合があります。関数で使用する依存関係を完全に制御するには、すべての依存関係をデプロイパッケージでパッケージングします。
-
依存関係の複雑さを最小限に抑えます。フレームワークを単純化して、実行環境起動時のロードを高速化します。
-
デプロイパッケージをランタイムに必要な最小限のサイズにします。これにより、呼び出しに先立ってデプロイパッケージをダウンロードして解凍する所要時間が短縮されます。
-
実行環境の再利用を活用して関数のパフォーマンスを向上させます。関数ハンドラー外で SDK クライアントとデータベース接続を初期化し、静的なアセットを
/tmp
ディレクトリにローカルにキャッシュします。関数の同じインスタンスで処理された後続の呼び出しは、これらのリソースを再利用できます。これにより、関数の実行時間が短縮され、コストが節約されます。呼び出し間でデータが漏れるのを防ぐため、実行環境を使用してセキュリティ上の懸念があるユーザーデータ、イベント、またはその他の情報を保存しないでください。関数がハンドラー内のメモリに保存できない変更可能な状態に依存している場合は、ユーザーごとに個別の関数または個別のバージョンの関数を作成することを検討してください。
-
keep-alive ディレクティブを使用して永続的な接続を維持します。Lambda は、時間の経過とともにアイドル状態の接続を消去します。関数を呼び出すときにアイドル状態の接続を再利用しようとすると、接続エラーが発生します。永続的な接続を維持するには、ランタイムに関連付けられている keep-alive ディレクティブを使用します。例については、「Node.js で Keep-alive を使用して接続を再利用する」を参照してください。
-
環境変数を使用して、オペレーショナルパラメータを関数に渡します。たとえば、Amazon S3 バケットに書き込む場合、書き込み先のバケット名はハードコーディングせずに、環境変数として設定します。
-
Lambda 関数では、再帰呼び出しを使用しないでください。関数が自身を呼び出すこともあれば、新たに開始されたプロセスで関数が再度呼び出される可能性もあります。これを行うと意図しないボリュームで関数が呼び出され、料金が急増する可能性があります。意図しない呼び出しがいくつも見つかった場合は、すぐに関数の予約済同時実行数を
0
に設定して、コードを更新している間のすべての関数の呼び出しをスロットリングします。 -
Lambda 関数コードで文書化されていない非公開の API を使用しないでください。AWS Lambda マネージドランタイムでは、Lambda が Lambda の内部 API にセキュリティと機能面の更新を定期的に適用します。これらの内部 API 更新には後方互換性がないことがあり、関数にこれらの非公開 API に対する依存関係がある場合、呼び出しの失敗などの意図しない結果につながります。公開されている API のリストについては、「API リファレンス」を参照してください。
-
冪等性コードを記述します。関数の記述に冪等性コードを使用すると、重複するイベントが同じ方法で処理されるようになります。コードでは、イベントを適切に検証し、重複するイベントを適切に処理する必要があります。詳細については、「Lambda 関数を冪等にするにはどうすればよいですか?
」を参照してください。