Lambda functions

Working with AWS is all about handling events. Your code will receive an event, and it should return something meaningful for that specific event.

Requirements

You need to make some adjustments to you application to make it compatible with AWS Lambdas, but it is easy, our python pd_aws_lambdaopen in new window package provides the tools to make it simple to handle HTTP and SQS events.

pip install awslambdaric

# Or use your favorite package manager
poetry add awslambdaric
1
2
3
4

You will also need to add awslambdaricopen in new window to your project.

pip install pd_aws_lambda

# Or use your favorite package manager
poetry add pd_aws_lambda
1
2
3
4

HTTP requests

For Web applications the most common event is triggered when an HTTP request is made to your URL. Amazon will receive the request and convert it into an event that is sent to your Lambda.

We provide an adapters that transforms the event into WSGI requests, and converts back your WSGI response into what AWS is expecting.

Specify the path to your WSGI application by setting PD_WSGI_APPLICATION environment variable.

TIP

For Flask projects it usually is your_project.app.
For default Django projects it will look like your_project.wsgi.application.

SQS messages

With SQS you can run background jobs that might not be suitable to run during your HTTP request handling, or you can schedule tasks to be executed at a certain time in the future.

Your Lambda function will be triggered whenever an SQS message needs to be handled. You specify the entrypoint by setting its path in PD_SQS_HANDLER environment variable.

Example handlers

The following is an example of a handler for SQS triggered events. It prints a json encoded message. The value will be logged in CloudWatch.

# file: sqs_handler.py
# PD_SQS_HANDLER=sqs_handler.my_sqs_handler
import json

def my_sqs_handler(event, context):
    """Read, json decode, and print the body of each record."""
    for record in event['Records']:
        # Lets assume that you sent a json encoded message.
        body = json.loads(record["body"])
        print(body)
1
2
3
4
5
6
7
8
9
10

A more elaborated handler can read the message, and then delegate for processing to a different function/actor specified in it:

# file: sqs_handler.py
# PD_SQS_HANDLER=sqs_handler.my_sqs_dispatcher
import importlib
import json

def my_sqs_dispatcher(event, context):
    """Read, json decode, and pass the message to an actor."""
    for record in event['Records']:
        # Lets assume that you sent a json encoded message.
        body = json.loads(record["body"])

        # `handler` should be a python path like
        # `my_project.handlers.my_handler`,
        # where `my_handler` is a function.
        handler_path = body.pop("handler")
        module, function = handler_path.rsplit(".", 1)
        app_module = importlib.import_module(module)
        handler = getattr(app_module, function)

        # Pass the message to the handler for processing.
        handler(**body)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Docker image

The following is an example Dockerfile that can be deployed with PythonDeploy and AWS Lambdas.

# Select the base image to use.
FROM python:3.8

# Define your application directory
ARG APP_DIR="/function"

# Set the working directory to your application root directory
WORKDIR ${APP_DIR}

# Install the AWS runtime interface and the PythonDeploy clients
#
# We recommend that you add these as dependencies to your project
# instead of adding them here.
RUN pip install \
        awslambdaric pd_aws_lambda

# Install your application dependencies.
COPY requirements.txt .
RUN pip install -r requirements.txt

# Copy your code.
COPY . .

# Important!
# This CMD is required for your image to be compatible with
# AWS Lambda and Python Deploy.
CMD [ "python", "-m", "awslambdaric", "pd_aws_lambda.dispatcher.dispatcher" ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

Environment variables

  • PD_WSGI_APPLICATION

    This should be the python path to you WSGI application.

  • PD_SQS_HANDLER

    If you are implementing background jobs with SQS, then all your SQS events will be passed to the method that you specify here. It will receive the Lambda event and context just as AWS provides them (example messageopen in new window).

  • PD_DEFAULT_HANDLER

    If you want a catch-all handler you can specify it with PD_DEFAULT_HANDLER. This needs to be the python path to your handler.

You only need to specify the ones that your application needs. For example, if you are not using SQS queues then PD_SQS_HANDLER is not needed, or if you are only dealing with SQS events, then PD_WSGI_APPLICATION is not needed.

Handler selection

The order in which handlers are selected is the following:

  1. Handler specified by handler_path in the event dataopen in new window.
  2. pd_aws_lambda.handlers.wsgi.handler if PD_WSGI_APPLICATION is specified and it is an event triggered by an Http request.
  3. PD_SQS_HANDLER if specified and it is an event triggered by an SQS message.
  4. PD_DEFAULT_HANDLER if specified and not handled by the previous handlers.
  5. pd_aws_lambda.handlers.wsgi.logger_handler as a catch-all handler.