Serverless Python — Building Lambda Functions with Python
In this tutorial, you will learn about Serverless Python. We cover key concepts, practical examples, and best practices to help you master this topic.
Python is one of the most popular runtimes for AWS Lambda, offering rich libraries for data processing, HTTP requests, and AWS service integration with minimal cold start overhead.
What You'll Learn
By the end of this lesson you will understand Python-specific Lambda patterns, dependency management, using libraries like boto3, requests, and Pillow, optimizing cold starts, and testing Python functions.
Why It Matters
Python's extensive ecosystem makes it powerful for serverless -- from data processing with Pandas to HTTP clients with requests to AWS integration with boto3. Understanding Python-specific patterns ensures efficient, cost-effective functions.
Real-World Use
DodaTech's file scanning Lambda functions use Python with boto3 for S3 interactions and custom malware signature matching. Python's concise syntax keeps the codebase small and maintainable.
# serverless_python.py
# Python Lambda basics
import json
import boto3
import os
def lambda_handler(event, context):
print(f"Python version: {os.environ.get('AWS_EXECUTION_ENV', 'local')}")
print(f"Event: {json.dumps(event)[:100]}...")
return {
"statusCode": 200,
"body": json.dumps({"message": "Hello from Python Lambda", "runtime": "Python 3.9"})
}
result = lambda_handler({"test": True}, None)
print(result["body"])
Expected output:
Python version: local
Event: {"test": true}...
{"message": "Hello from Python Lambda", "runtime": "Python 3.9"}
Dependency Management
Use the serverless-python-requirements plugin to bundle dependencies. Use layers for shared libraries.
# serverless.yml with Python requirements
plugins:
- serverless-python-requirements
custom:
pythonRequirements:
dockerizePip: true # Use Docker for native binaries
slim: true # Remove tests and caches
layer: true # Create a separate layer for dependencies
functions:
processImage:
handler: handlers/image.process
layers:
- {Ref: PythonRequirementsLambdaLayer}
# handlers/image.py
# Using Pillow from a layer
import json
def process(event, context):
print("Image processing function initialized")
print("Pillow library available from Python requirements layer")
for record in event.get("Records", []):
key = record["s3"]["object"]["key"]
print(f"Processing image: {key}")
return {"statusCode": 200, "body": json.dumps({"processed": len(event.get("Records", []))})}
test = {"Records": [{"s3": {"object": {"key": "photo.jpg"}}}]}
print(process(test, None)["body"])
Working with boto3
boto3 is the AWS SDK for Python, pre-installed in the Lambda runtime.
# boto3_examples.py
# Using boto3 in Lambda
import json
import boto3
from boto3.dynamodb.conditions import Key
# Initialize clients outside handler
s3 = boto3.client("s3")
dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table(os.environ.get("TABLE_NAME", "users"))
import os
def lambda_handler(event, context):
# List S3 objects
bucket = os.environ.get("BUCKET", "my-bucket")
response = s3.list_objects_v2(Bucket=bucket, MaxKeys=10)
print(f"S3 objects in {bucket}: {response.get('KeyCount', 0)}")
# Query DynamoDB
user_id = event.get("pathParameters", {}).get("id")
if user_id:
result = table.query(
KeyConditionExpression=Key("pk").eq(f"USER#{user_id}")
)
print(f"DynamoDB result: {result.get('Items', [])}")
return {"statusCode": 200, "body": json.dumps({"status": "ok"})}
os.environ["TABLE_NAME"] = "users"
os.environ["BUCKET"] = "my-bucket"
print(lambda_handler({"pathParameters": {"id": "1"}}, None)["body"])
Common Mistakes
Forgetting to use json.dumps on return values: Lambda expects string bodies. Python dicts must be serialized with json.dumps.
Not handling encoding issues: External data may have unexpected encodings. Use try/except with encoding detection.
Using Pandas without layer optimization: Pandas is large (50MB+). Use a dedicated Lambda layer and consider alternatives like polars for smaller deployments.
Ignoring Python version compatibility: Lambda supports specific Python versions. Use the same version locally as in production.
Not using virtual environments for local testing: Always use venv or conda to match the Lambda runtime environment.
Practice Questions
What is the default Python runtime version for AWS Lambda? AWS Lambda supports Python 3.9, 3.10, 3.11, 3.12, and 3.13.
How do you bundle Python dependencies for Lambda? Use serverless-python-requirements plugin, pip install -t, or container images.
Why use slim mode for Python requirements? It removes test files, caches, and .pyc files from the deployment package, reducing size and cold start time.
How do you handle binary data in Python Lambda? Use base64 encoding for JSON responses or set binary content types in API Gateway.
Challenge: Create a Python Lambda function that reads a CSV from S3, processes it with the csv module, and stores results in DynamoDB.
FAQ
Mini Project
Create a Python Lambda function that uses boto3 to query DynamoDB for user data, processes it, and returns a formatted response.
import json
import os
def lambda_handler(event, context):
pk = event.get("pk", "USER#1")
print(f"Querying DynamoDB for {pk}")
result = query_dynamodb(pk)
user = result.get("Item", {})
return {
"statusCode": 200,
"body": json.dumps({
"userId": user.get("id"),
"name": user.get("name"),
"email": user.get("email")
})
}
def query_dynamodb(pk):
return {"Item": {"id": "1", "name": "Alice", "email": "alice@example.com"}}
print(json.loads(lambda_handler({"pk": "USER#1"}, None)["body"]))
What's Next
Next: Serverless Node.js for Node.js patterns.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro