Create Python Function on AWS Lambda Using Serverless

Awhile back I wrote a tutorial on how to Create an AWS Lambda Function Using Serverless. The tutorial is good for getting started, but Lambda Functions often process input as well as have dependencies on other Python packages. This serverless tutorial goes further and shows you how to create, deploy, and invoke a Python Lambda Function on AWS that calculates the mean of an array of integers. The function requires a JSON array of integers as input and has a dependency on numpy to calculate the mean.

Create Virtual Environment and Pip Install Python Dependencies

Since we’re using Python 3, let’s create a new virtual environment and pip install the numpy dependency. We’ll also create the requirements.txt file that will list the Python dependencies.

$ mkdir serverless-python && cd $_
$ python -m venv env
$ source env/bin/activate
$ (env) pip install numpy
$ (env) pip freeze > requirements.txt

Create Serverless Python Service and Configure Serverless.yml

Create a serverless numpy-stats service for AWS using the Python 3 template. This will create two files: handler.py and serverless.yml.

$ serverless create --name numpy-stats --template aws-python3

Alter the serverless.yml file as shown below. The AWS Lambda Function will run using Python 3.6, and the mean function that calculates the mean of the integers will be located in the handler.py module.

We are using the serverless-python-requirements custom plugin to help us bundle the numpy Python dependency. The plugin is an npm package and uses Docker to do its magic. We will install serverless-python-requirements in a later step.

service: numpy-stats

provider:
  name: aws
  runtime: python3.6

functions:
  mean:
    handler: handler.mean

plugins:
  - serverless-python-requirements

custom:
  pythonRequirements:
    dockerizePip: non-linux

Write the AWS Lambda Python Function

Serverless provides some default code for Python. I changed the code so it uses numpy to calculate the mean of an array of integers.

import json
import numpy as np


def mean(event, context):
    values = event['values']
    np_array = np.array(values)
    mean = np.mean(np_array)

    response = {
        "statusCode": 200,
        "body": json.dumps(mean)
    }

    return response


if __name__ == '__main__':
    resp = mean({'values': [1, 2, 3, 4, 5]}, None)
    print(resp)

You can test the AWS Lambda function locally to make sure it works.

$ (env) python handler.py
{'statusCode': 200, 'body': '3.0'}

Install serverless-python-requirements Plugin

Install the serverless-python-requirements plugin that uses Docker to bundle the Python dependencies for us.

$ (env) npm init -f
$ (env) npm install --save serverless-python-requirements

Deploy the Python AWS Lambda Function

Deploy the service to AWS using serverless. Be patient while it installs the Python dependencies, prepares the Docker container, creates the CloudFormation Stack, and uploads the code.

$ (env) serverless deploy

Serverless: Installing required Python packages with python3.6...
Serverless: Docker Image: lambci/lambda:build-python3.6
Serverless: Linking required Python packages...
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Unlinking required Python packages...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (33.78 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
Serverless: Stack update finished...

Invoke the Lambda Function Using Serverless

Invoke the AWS Lambda Function using serverless.

$ (env) serverless invoke -f mean -d '{"values": [1, 2, 3, 4, 5]}'
{
    "statusCode": 200,
    "body": "3.0"
}

Clean Up Resources

Remove the Lambda Function and all resources used by serverless to deploy it.

$ (env) serverless remove

Deactivate Python 3 Virtual Environment

Deactivate the Python 3 Virtual Environment.

$ (env) deactivate
$

Conclusion

In a future serverless tutorial we will add an HTTP endpoint using the AWS API Gateway so we can call the Lambda function using cURL or other HTTP Client.

If you’d like to deploy Python Flask to AWS, read the following tutorial: Deploy Serverless Python Flask App to AWS Using Zappa.

Contents