I wrote AWS Lambda, and I was a little addicted to the default value of Python arguments

Background

In AWS Lambda's Python code, I created a function that returns a result based on a specified date (one year ago if not specified).

from datetime import datetime
from dateutil.relativedelta import relativedelta

one_year_ago = (datetime.now() - relativedelta(years=1)).isoformat()[:-3] + "Z"

def lambda_handler(event, context):

    #Function in question
    def test_func(last_time: str = one_year_ago) -> str:
        return "last_time: " + last_time

    print(one_year_ago)

    #Where the function is called
    print(test_func("2019-09-20T06:28:26.000Z"))
    print(test_func())

    return 0


lambda_handler("","")


Execution result

2018-12-08T20:22:57.183Z
last_time: 2019-09-20T06:28:26.000Z
last_time: 2018-12-08T20:22:57.183Z

According to AWS Lambda's Best Practices, it is better to separate the logic. Because it was a thing, I corrected it as follows.

from datetime import datetime
from dateutil.relativedelta import relativedelta

one_year_ago: str = ""

def lambda_handler(event, context):
    global one_year_ago
    one_year_ago = (datetime.now() - relativedelta(years=1)).isoformat()[:-3] + "Z"
    print(one_year_ago)
    
    #Where the function is called
    print(test_func("2019-09-20T06:28:26.000Z"))
    print(test_func())
    return 0

#Function in question
def test_func(last_time: str = one_year_ago) -> str:
    return "last_time: " + last_time


lambda_handler("","")

--Other than the Lambda handler part, it is called only at the time of cold start [^ 1], so it is in the handler to ask for one year ago.

  • Therefore, the first code itself does not work properly. --Define the variable with an empty string in advance (otherwise it will be "not defined").

What happened

If you specify a date, it works, but if you do not specify it, an error occurs. The default value seems to be disabled.


Execution result

2018-12-08T20:15:21.611Z
last_time: 2019-09-20T06:28:26.000Z
last_time: 
  • The actual code was throwing a boto3 request, and the error InvalidParameterValueException [^ 2] was output.

Conclusion

The default argument is evaluated only the first time, so the first empty string has been set. https://note.nkmk.me/python-argument-default/

I think it's not cool, but I avoided it by doing the following for the time being.
Code

from datetime import datetime
from dateutil.relativedelta import relativedelta

one_year_ago: str = ""

def lambda_handler(event, context):
    global one_year_ago
    one_year_ago = (datetime.now() - relativedelta(years=1)).isoformat()[:-3] + "Z"
    print(one_year_ago)

    #Where the function is called
    print(test_func("2019-09-20T06:28:26.000Z"))
    print(test_func())
    return 0

#Function in question
def test_func(last_time: str = "one_year_ago") -> str:
    if last_time == "one_year_ago":
        last_time = one_year_ago
    return "last_time: " + last_time


lambda_handler("","")


Execution result

2018-12-08T20:21:13.942Z
last_time: 2019-09-20T06:28:26.000Z
last_time: 2018-12-08T20:21:13.942Z

Digression

――I think there seems to be a more beautiful way of writing. ――There is a feeling of being forced to ask for a year ago. ..

  one_year_ago = (datetime.now() - relativedelta(years=1)).isoformat()[:-3] + "Z"

--Actually, I want to store the inquiry history to AWS support in DynamoDB, I'm writing this code.

  def cases_get(last_time: str = "one_year_ago") -> list:
    if last_time == "one_year_ago":
        last_time = one_year_ago
    cases_detail: list = []
    for lang in ("ja", "en"):
        for page in cases_paginator.paginate(
            includeResolvedCases=True,
            maxResults=100,
            language=lang,
            includeCommunications=False,
            afterTime=last_time,
        ):
            for cases in page["cases"]:
                cases["displayId"] = int(cases["displayId"])
                cases["yearIndex"] = int(cases["timeCreated"][:4])
                cases_detail.append(cases)

    return cases_detail

Recommended Posts

I wrote AWS Lambda, and I was a little addicted to the default value of Python arguments
Summary of points I was addicted to running Selenium on AWS Lambda (python)
A story that I was addicted to calling Lambda from AWS Lambda.
[Python] I wrote a REST API using AWS API Gateway and Lambda.
The file name was bad in Python and I was addicted to import
[Python] I was addicted to not saving internal variables of lambda expressions
Use AWS lambda to scrape the news and notify LINE of updates on a regular basis [python]
It was a life I wanted to OCR on AWS Lambda to locate the characters.
I just changed the sample source of Python a little.
I want to know the features of Python and pip
[Fixed] I was addicted to alphanumeric judgment of Python strings
I was surprised to receive a nice review when I wrote Python to CheckIO and its explanation
I tried to create a Python script to get the value of a cell in Microsoft Excel
I wrote a doctest in "I tried to simulate the probability of a bingo game with Python"
I wrote a script to create a Twitter Bot development environment quickly with AWS Lambda + Python 2.7
[Introduction to Python] I compared the naming conventions of C # and Python.
I wrote the code to write the code of Brainf * ck in python
I want to use both key and value of Python iterator
I was addicted to confusing class variables and instance variables in Python
[Python] The role of the asterisk in front of the variable. Divide the input value and assign it to a variable
I want to clear up the question of the "__init__" method and the "self" argument of a Python class.
What I was addicted to Python autorun
I wanted to be careful about the behavior of Python's default arguments
A story I was addicted to when inserting from Python to a PostgreSQL table
I was addicted to creating a Python venv environment with VS Code
I tried to verify and analyze the acceleration of Python by Cython
I made a program to check the size of a file in Python
I tried to display the altitude value of DTM in a graph
Python: I want to measure the processing time of a function neatly
I made a function to see the movement of a two-dimensional array (Python)
[Fabric] I was addicted to using boolean as an argument, so make a note of the countermeasures.
I was able to recurse in Python: lambda
I wrote a class in Python3 and Java
Summary of studying Python to use AWS Lambda
A discussion of the strengths and weaknesses of Python
Three things I was addicted to when using Python and MySQL with Docker
AtCoder AGC 041 C --I was addicted to the full search of Domino Quality
Build a python environment to learn the theory and implementation of deep learning
A note I was addicted to when running Python with Visual Studio Code
I made a script to record the active window using win32gui of Python
A story that I was addicted to when I made SFTP communication with python
I set up TensowFlow and was addicted to it, so make a note
I thought it was the same as python, and I was addicted to the problem that the ruby interpreter did not start.
[Python & SQLite] I tried to analyze the expected value of a race with horses in the 1x win range ①
I created a Slack bot that confirms and notifies AWS Lambda of the expiration date of an SSL certificate
I was soberly addicted to calling awscli from a Python 2.7 script registered in crontab
I tried to notify the update of "Become a novelist" using "IFTTT" and "Become a novelist API"
[Introduction to statistics] What kind of distribution is the t distribution, chi-square distribution, and F distribution? A little summary of how to use [python]
I tried to automate the article update of Livedoor blog with Python and selenium.
The concept of reference in Python collapsed for a moment, so I experimented a little.
I checked out the versions of Blender and Python
I was addicted to scraping with Selenium (+ Python) in 2020
Try running a Schedule to start and stop an instance on AWS Lambda (Python)
It was a little difficult to do flask with the docker version of nginx-unit
I checked the default OS and shell of docker-machine
I want to AWS Lambda with Python on Mac!
A story that I was addicted to at np.where
[Python & SQLite] I analyzed the expected value of a race with horses with a win of 1x ②
The timing when the value of the default argument is evaluated is different between Ruby and Python.
I was able to repeat it in Python: lambda
A little trick to know when writing a Twilio application using Python on AWS Lambda