AWS Lambda Functions Made Easy
AWS Lambda Functions Made Easy
A Step by Step Guide with Code Snippets for Packing Your Python 2.7 Function for AWS Lambda
Background
I hope the code in this blog post will save you a lot of time developing serverless functions for AWS Lambda.
Creating simple functions using the Lambda web console is easy. As I found in a recent
This blog post walks you through creating and packaging an AWS Lambda function for Python 2.7 using the boto3
client, and includes extra sections on invoking Lambda functions, and repackaging and re-uploading while the code is still in development.
Pre-Requisites
- pip, a tool for installing Python packages.
- Virtual environments, a tool to create isolated Python environments
- Boto3. This tutorial assumes that you are familiar with using AWS’s
boto3
Python client, and that you have followed AWS's instructions to configure your AWS credentials.
Write A Function
Lambda functions need an entry point handler that accepts the arguments event
and context
. A basic Lambda function will treat event
as a key-value store of arguments to the function, and may ignore context
. As an example, in Python:
# file: main.py
def handler(event, context):
plotly_url = event['plotly_url']
The file and function names matter! Both values are used below in Create a Lambda Function. This example assumes a file main.py
contains a function handler
.
If you’d like, you can use my example Lambda function that I created to help me debug machine learning models running remotely. My function takes a Plotly url, downloads the image, and sends it to me over Slack (created because Plotly plots don’t load image previews in Slack). Clone/fork the repo, or just download main.py
and requirements-lambda.txt
.
Install Dependencies
To keep function dependencies (in my example plotly
and slackclient
) separate from development dependencies (like boto3
) use separate Python virtual environments. Put all Python dependencies in requirements-lambda.txt
. This bash code snippet creates a fresh Python virtual environment and installs dependencies from requirements-lambda.txt
:
export VIRTUALENV='venv_lambda'
rm -fr $VIRTUALENV
# Setup fresh virtualenv and install requirements
virtualenv $VIRTUALENV
source $VIRTUALENV/bin/activate
pip install -r requirements-lambda.txt
deactivate
Create .zip File
Zip files are required for Lambda functions that include Python package dependencies, whether the code is uploaded through the web, the Python client, or s3.
This bash snippet creates lambda.zip
from main.py
and the dependencies in the previous step:
export VIRTUALENV='venv_lambda'
export ZIP_FILE='lambda.zip'
export PYTHON_VERSION='python2.7'
# Zip dependencies from virtualenv, and main.py
cd $VIRTUALENV/lib/$PYTHON_VERSION/site-packages/
zip -r9 ../../../../$ZIP_FILE *
cd ../../../../
zip -g $ZIP_FILE main.py
Create a Basic IAM Role
This Python snippet uses boto3
to create an IAM role named LambdaBasicExecution
with basic lambda execution permissions.
import json, boto3
# From https://alestic.com/2014/11/aws-lambda-cli/
role_policy_document = {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
iam_client = boto3.client('iam')
iam_client.create_role(
RoleName='LambdaBasicExecution
',
AssumeRolePolicyDocument=json.dumps(role_policy_document),
)
Create a Lambda Function
By now lambda.zip
contains a handler and dependencies, and your AWS account has an IAM role with lambda privileges (see previous section).
Environment Variables: If your function depends on environment variables (the example code I provided above requires a few), set them below in the environment_variables
dict. These will be easy to edit later in the console.
The following Python snippet will use all of the resources above to create a new AWS Lambda function called myLambdaFunction
:
import boto3
iam_client = boto3.client('iam')
lambda_client = boto3.client('lambda')
env_variables = dict() # Environment Variables
with open('lambda.zip', 'rb') as f:
zipped_code = f.read()
role = iam_client.get_role(RoleName='LambdaBasicExecution
')
lambda_client.create_function(
FunctionName='myLambdaFunction',
Runtime='python2.7',
Role=role['Role']['Arn'],
Handler='main.handler',
Code=dict(ZipFile=zipped_code),
Timeout=300, # Maximum allowable timeout
Environment=dict(Variables=env_variables),
)
View, edit and test functions on the AWS console.
Invoke Your Function
First, define your test_event
(a dictionary that will be passed as the first argument to the function). Then, use the Python snippet below to invoke myLambdaFunction
:
import boto3, json
lambda_client = boto3.client('lambda')
lambda_client.invoke(
FunctionName='myLambdaFunction',
InvocationType='Event',
Payload=json.dumps(test_event),
)
(Optional) Re-Upload Code
Inevitably, your code (or my code) won’t work the first time, and you’ll need to tweak it.
Re-run Install Dependencies if any dependencies changed, and re-run Create .zip File to repackage all code.
Use the following Python snippet to update the code for an existing lambda function:
import boto3
lambda_client = boto3.client('lambda')
with open('lambda.zip', 'rb') as f:
zipped_code = f.read()
lambda_client.update_function_code(
FunctionName='myLambdaFunction',
ZipFile=zipped_code,
)