【Lambda】datetimeで正しい日時の取得ができない。

はじめに

datetimeで日付を取得して今日のデータだけを取り出そうと思ったらなぜかうまくいきませんでした。

原因を調査したところ、「そもそもdatetimeで取得した日付が正しくない!!」

ということに気がついてしまいました。

問題のコード

問題が起こっているのはコードの以下の部分でした。

import datetime

date = datetime.datetime.now()

def lambda_handler(event, context):
    print(date)

これを実行すると1度目は正常に日時が取得できるのですが、2度目も同じ日時が表示されてしまいます。

1回目
----------------------------
2019-03-11 04:10:18.728639
2回目
----------------------------
2019-03-11 04:10:18.728639

原因

調べてみたら、lambda_handler外(グローバル部分)でdatetimeを変数宣言していたことが原因だったようです。Lambdaは関数を実行する際にインスタンスを再利用することがあるのでキャッシュが残っているとそれが関数の実行時に再利用されてしまいます。Lambdaの関数インスタンスの再利用についてはAWSのよくある質問で言及されていました。

Q: AWS Lambda は関数インスタンスを再利用しますか?

パフォーマンス向上のため、AWS Lambda は新しく関数のインスタンスを作成するのではなく、関数のインスタンスを保持してその後のリクエストに対応することがあります。Lambda で関数インスタンスを再利用する方法の詳細については、AWS のドキュメントを参照してください。ただし、常にインスタンスを再利用するわけではありません。

今回の場合は最初に取得した日付がキャッシュに残っていて、2回目以降の関数実行時に日付が再利用されてしまったということでした。

対処法

lambda_handler関数内でdatetimeを呼び出すようにしたところ正常に日時が取得できるようになりました。

import datetime

def lambda_handler(event, context):
    date = datetime.datetime.now()
    print(date)

コードを編集したところ以下のように正しい日時を取得することができました。

1回目
----------------------------
2019-03-11 04:19:11.112293
2回目
----------------------------
2019-03-11 04:20:35.442823

さいごに

slackで1日の天気予報を通知してみた。」のコードでは日付だけ取得して使っていたため、この問題に気が付くのが遅くなってしまいました。Lambdaを利用するときはキャッシュにも注意する必要があると実感しました。

今回の記事ではUTCの日時が表示されてしまうので次回はUTC時刻からJST時刻に変えていきたいと思います。

次の記事 → 日付を取得したらUTCだった…。