Watch out for global variables outside of lambda_handler (datetime)

Introduction

Get the time (residence time) between the creation of the job and the execution of Lambda When I was creating Lambda I was using datetime to get the current date and time, So I was addicted to "AWS Lambda reuses function instances", so I would like to make an article.

The code I was writing first

First to get the current date and time when Lambda was executed Below is a simplified version of the code.

from datetime import datetime

now = datetime.now()

def lambda_handler(event, context):
    method_a()

def method_a():
    method_b()

def method_b():
    method_c()

def method_c():
#x represents the date and time when the job was created.
   time = now - x
   print(data)

--Job creation time is x --Current time is now --The residence time is time

It is expressed as.

Declare now as a global variable to represent the time I made it possible to use any method.

I succeeded locally, but ...

Since I was able to get the residence time locally, I built and deployed it as it is and created Lambda. The first Lambda test was also successful and there were no issues.

All right! Let's test it again and check ...

that! ?? The residence time is strange! !! !! !! !! !!

The residence time that was successfully obtained in the first time I couldn't get it well after the second time.

Time is strange no matter how many times I try.

So build and deploy again I updated Lambda and it worked.

However, it was no good after the second time.

The cause is

So when I was investigating various things to investigate the cause I came across an article here!

The cause was the global variable now declared outside of lambda_handler.

Apparently Lambda is for performance improvement It's like reusing an instance of a function.

https://aws.amazon.com/jp/lambda/faqs/ image.png

In other words, the date and time of the first acquired now is cached. It seems that the same value was reused from the second time onward.

Whenever a Lambda function instance is newly created I was thinking, so I didn't notice it at all! !!

I want to put a variable globally in lambda_handler

After understanding the cause For the time being, I put now in lambda_handler. Now every time Lambda runs, it will get a new now date and time.

from datetime import datetime

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

def method_a(now):
    method_b(now)

def method_b(now):
    method_c(now)

def method_c(now):
#x represents the date and time when the job was created.
   time = now - x
   print(data)

It can be done in this form as well, It's not cool to pass it via a method like this I fixed it as follows.

from datetime import datetime

def lambda_handler(event, context):
    global now 
    now = datetime.now()
    method_a()

def method_a():
    method_b()

def method_b():
    method_c()

def method_c():
#x represents the date and time when the job was created.
   time = now - x
   print(data)

This is safe, even after the second time Now you can get the date and time when now was executed properly. I was able to get time well.

Summary

About reuse of Lambda function instance It was my first time hearing, so I learned a lot.

After that, global variables are very convenient, That it is easy to cause unexpected bugs I realized it with my own body.

I will be careful about how to use it.

Recommended Posts

Watch out for global variables outside of lambda_handler (datetime)
Watch out for the return value of __len__
Watch out for randint
Declaration of C global variables
2015-03-25 python> Multi-line comment> Watch out for indent
The story of manipulating python global variables
Find out the day of the week with datetime