クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

Lambda ハンドラーとイベント

このレッスンのあとで: イベントを読み、結果を返すハンドラーを、書くことができる。

55分のレッスンコマンドなし

知らせを待つ関数

Lambda ハンドラーは、何かが起きたときに、クラウドのサービスが代わりに呼んでくれる関数です。たとえば、写真が S3 バケットに届いたときです。知らせは、イベントという辞書で届きます。

このモジュールでは、ハンドラーを書き、自分のパソコンで試します。何もどこにもデプロイせず、イベントは手で作ります。

このレッスンのゴール

メモ

イベントを読み、結果を返すハンドラーを、書くことができる。

キーワード

ことばいみれい
ハンドラーサービスが呼ぶ関数handler(event, context)
イベント何が起きたかを書いた辞書
レコードイベントの知らせの並びの、1件
フィクスチャテスト用に取っておく、作り物のイベント
冪等2回実行しても、同じ結果になること

学生が入力するセルは、このプレビューでは空白です。

ハンドラーは、イベントとコンテキストを受け取る

ハンドラーは、引数が2つある、ふつうの Python の関数です。event は知らせを持ちます。context は、実行中の関数についての事実を持ちます。たとえば、何秒まで動いてよいか、です。

関数は結果を返します。ただの関数なので、作り物のイベントで、自分で呼ぶことができます。

どこにもデプロイしない

メモ

このモジュールでは、関数を1つもアップロードしません。ここのイベントの形は、関数が受け取る、文書にある形で、あなたのスタックの出力ではありません。試すときは、手で作ったイベントを渡して、関数を呼びます。テスト用に取っておく、この作り物のイベントを、フィクスチャと呼びます。

実行: ハンドラーを手で呼ぶ

コード: python
event = {
    "Records": [
        {
            "eventSource": "aws:s3",
            "eventName": "ObjectCreated:Put",
            "s3": {"bucket": {"name": "shop-uploads"}, "object": {"key": "images/cat.png", "size": 1024}},
        }
    ]
}

def handler(event, context):
    first = event["Records"][0]
    bucket = first["s3"]["bucket"]["name"]
    key = first["s3"]["object"]["key"]
    return {"stored": bucket + "/" + key}

print(handler(event, None))
# key を images/dog.png に変えて、もう一度実行しましょう。

イベントは、レコードの並びを持つ

1つのイベントが、何件ものレコードを運ぶことがあります。だから、ハンドラーは Records を順に回します。各レコードは、eventSource で、どこから来たかを言います。

S3 のレコードは、バケットとキーを言います。キューからの SQS のレコードは、body を持ちます。body は文字列なので、JSON の body は、json.loads で読んでから使います。

例: 2種類のレコード

項目S3 のレコードSQS のレコード
eventSourceaws:s3aws:sqs
何が起きたかeventName。たとえば ObjectCreated:Putbody にあるメッセージ
どこを見るかs3.bucket.name と s3.object.keybody。JSON の文字列
一意な id頼れるものはないmessageId

学生が入力するセルは、このプレビューでは空白です。

実行: 2種類のレコードを読む

コード: python
import json

event = {"Records": [
    {"eventSource": "aws:sqs", "messageId": "m-1", "body": "{\"order\": 1, \"item\": \"tea\"}"},
    {"eventSource": "aws:s3", "eventName": "ObjectCreated:Put",
     "s3": {"bucket": {"name": "shop-uploads"}, "object": {"key": "logs/web.log"}}},
]}

def handler(event, context):
    seen = []
    for record in event["Records"]:
        if record["eventSource"] == "aws:sqs":
            order = json.loads(record["body"])
            seen.append("注文 " + str(order["order"]))
        elif record["eventSource"] == "aws:s3":
            seen.append("ファイル " + record["s3"]["object"]["key"])
    return seen

print(handler(event, None))

同じ知らせを2回受けることがある

キューは、少なくとも1回の配信を約束します。同じメッセージが、関数に2回届くことがあります。たとえば、実行が遅かったあとです。

2回目の実行で何も変わらないとき、ハンドラーは冪等です。終えた仕事を書き留め、すでに書いてある仕事は飛ばします。本物の関数は、その記録を表に置き、あとのパイプラインの回がそれを使います。ここでは、集合がその代わりをします。

よくある間違い

注意

各メッセージは、1回だけ届く、と考える人が多いです。届きません。配信は、少なくとも1回です。ハンドラーを、2回実行しても安全にしておかないと、1件の注文に、2回請求することになります。

実行: すでにした仕事を飛ばす

コード: python
def handle(orders, done):
    newly = []
    for order in orders:
        if order in done:
            continue
        done.add(order)
        newly.append(order)
    return newly

done = set()
print(handle([1, 2, 2], done))
print(handle([2, 3], done))
# 2つ目のリストを [4, 1] に変えましょう。Run の前に、2行目を予想しましょう。

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。