Serverless Computing in Python with AWS::Lambda

Calum Macdonald
4 min readNov 9, 2020

--

There are no surprises that AWS and other companies want people to use and move over to serverless computing. There are many advantages, particularly for small companies and independent researchers (like myself), to take advantage of and learn about.

I used AWS’s tutorials to build a simple python hello-world script and run it as an AWS Lambda…

To follow what I did, you will need to have signed up to (at least) and aws free account. And have the aws command line client installed and configured with your own credentials on your machine. I also assume some basic knowledge of AWS.

As of November 2020, the AWS free-tier account gives you:

The AWS Lambda free usage tier includes 1M free requests per month and 400,000 GB-seconds of compute time per month.

This, plus the the pricing plan, makes using AWS Lambda very cost effective if you are wanting to execute many small pieces of code with no need for a fixed IP (however, you can configured to run on an AWS VPC, if you want).

Be aware, there are limits and quotas which you should check out before deciding if AWS Lambda is worth using for your project!

Create a Trust-Policy

The first thing to do is we need to create a new policy to give us the permissions to be able to create a new lambda function:

$ cat trust-policy.json 
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}

There are many examples out there describing what this means and other ways of doing this.

Once we have created a policy, we can upload it to our account via the command line:

$ aws iam create-role --role-name lambda-ex --assume-role-policy-document file://trust-policy.json
{
"Role": {
"Path": "/",
"RoleName": "lambda-ex",
"RoleId": "AROA3GBENLBA5W3OEPEKR",
"Arn": "arn:aws:iam::XXXXXXXXXXX:role/lambda-ex",
"CreateDate": "2020-11-09T12:55:32+00:00",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
}
}

As can be seen, the command will return a response that tells us what our IAM role (arn) for the policy is "Arn": "arn:aws:iam::XXXXXXXXXXX:role/lambda-ex" . It’s important to record this for later.

Create a python function

Next we create a python function we want to execute on AWS Lambda. In this stupidly simple example, we retrieve two numbers ( x,y ) and a string ( msg ) and return the string formatted in lower case and the product and difference of the two numbers.

$ cat lambda_function.py 
import json
def lambda_handler(event, context):
x = event['x']
y = event['y']
msg = event['msg']
return {
'statusCode': 200,
'msg': json.dumps(msg.lower()),
'product': x*y,
'diff': x-y
}

To upload to AWS::Lambda, the function needs to be placed in a deployment .zip file first:

zip my-deployment-package.zip lambda_function.py

Obviously more files with complex functionality can be deployed like this. These docs show how additional requirements can be added to create a package.

Create a new AWS::Lambda function

Now we have the IAM role and the ‘deployment package’ defined, we can upload and create a new lambda function (using python3.8 ):

$ aws lambda create-function --function-name test-message --zip-file fileb://my-deployment-package.zip --runtime python3.8 --role arn:aws:iam::XXXXXXXXXX:role/lambda-ex --handler lambda_function.lambda_handler
{
"FunctionName": "test-message",
"FunctionArn": "arn:aws:lambda:eu-west-2:768875518017:function:test-message",
"Runtime": "python3.8",
"Role": "arn:aws:iam::XXXXXXXXXXX:role/lambda-ex",
"Handler": "lambda_function.lambda_handler",
"CodeSize": 327,
"Description": "",
"Timeout": 3,
"MemorySize": 128,
"LastModified": "2020-11-09T13:04:46.867+0000",
"CodeSha256": "a4mwsNGL5ib6f+c355TzY7MmaxgzukXg2djMBXXZQA0=",
"Version": "$LATEST",
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "a520f814-7772-4534-b5cd-4707f3a286d9",
"State": "Active",
"LastUpdateStatus": "Successful"
}

Please note that for the value of --handler you need:

<name_of_file>.<name_of_function>

We defined def lambda_handler in lambda_function.py, therefore in this scenario the name needed is lambda_function.lambda_handler

Create an input to parse

As described above, the handler (lambda) is expecting to receive three variables via event, which it is going to perform some operations on. We can defined what these variables are in another json file that will be sent to the lambda function:

$ cat message.json 
{
"msg":"Ey UP maTe",
"x": 112321,
"y": 232390
}

Run the lambda function

Using invoke the function can be executed, sending the message.json file, and returning the output into response.json:

$ aws lambda invoke --function-name test-message --payload fileb://message.json response.json

Checking the response, we will see that it succeeded!

$ cat response.json 
{"statusCode": 200, "msg": "\"ey up mate\"", "product": 26102277190, "diff": -120069}
AWS Lambda Dashboard

AWS Lambda Console allows you to setup much of this via the online dashboard and keep an eye on how much resources you are using!

Today I showed you what was an incredibly basic example of executing some python code on a serverless cloud. AWS::Lambda could be a very convenient solution for you, for example if you need to parallel compute 1000s of short processes but don’t need all the high performance infrastructure (nor have the time to setup) of AWS::Batch or similar Cloud Providers.

--

--

Calum Macdonald
Calum Macdonald

Written by Calum Macdonald

Particle Physicist // Data Scientist // Data Analyst

No responses yet