This article is the 23rd day of Serverless (2) Advent Calendar 2016.
The following two frameworks seem to be popular for developing serverless applications in Python.
This time, let's roughly compare these two.
By the way, if you use Node.js, Serverless Framework and Apex are famous. The following slides will help you find out what other serverless frameworks are available. Unlimited Frameworks
chalice Python Serverless Microframework for AWS
This is the only command that is prepared.
Commands:
deploy
gen-policy
generate-sdk
local
logs
new-project
url
Let's take a look at the source code using the actual chalice by referring to How to create a thumbnail API service with AWS Lambda.
ʻApp.py` does the process of receiving photos by POST and generating thumbnails.
import base64
import uuid
from subprocess import Popen, PIPE
import boto3
from chalice import BadRequestError, Chalice
app = Chalice(app_name='thumbnail-service')
app.debug = True # TODO: Disable on production
S3 = boto3.client('s3')
S3_BUCKET = '' # TODO: Replace with valid bucket name
@app.route('/', methods=['POST'])
def index():
body = app.current_request.json_body
image = base64.b64decode(body['data'])
format = {'jpg': 'jpeg', 'png': 'png'}[body.get('format', 'jpg').lower()]
mode = {'max': '', 'min': '^', 'exact': '!'}[body.get('mode', 'max').lower()]
width = int(body.get('width', 128))
height = int(body.get('height', 128))
cmd = [
'convert', # ImageMagick Convert
'-', # Read original picture from StdIn
'-auto-orient', # Detect picture orientation from metadata
'-thumbnail', '{}x{}{}'.format(width, height, mode), # Thumbnail size
'-extent', '{}x{}'.format(width, height), # Fill if original picture is smaller than thumbnail
'-gravity', 'Center', # Extend (fill) from the thumbnail middle
'-unsharp',' 0x.5', # Un-sharpen slightly to improve small thumbnails
'-quality', '80%', # Thumbnail JPG quality
'{}:-'.format(format), # Write thumbnail with `format` to StdOut
]
p = Popen(cmd, stdout=PIPE, stdin=PIPE)
thumbnail = p.communicate(input=image)[0]
if not thumbnail:
raise BadRequestError('Image format not supported')
filename = '{}_{}x{}.{}'.format(uuid.uuid4(), width, height, format)
S3.put_object(
Bucket=S3_BUCKET,
Key=filename,
Body=thumbnail,
ACL='public-read',
ContentType='image/{}'.format(format),
)
return {
'url': 'https://s3.amazonaws.com/{}/{}'.format(S3_BUCKET, filename)
}
Zappa
Serverless Python Web Services
Then, like chalice, the application that generates thumbnails of the photos received by POST is [Building Serverless Microservices with Zappa and Flask --Gun.io](https://gun.io/blog/serverless-microservices-with-zappa-and Let's refer to -flask /).
import base64
import boto3
import calendar
import io
from datetime import datetime, timedelta
from flask import Flask, request, render_template
from PIL import Image
s3 = boto3.resource('s3')
BUCKET_NAME = 'your_public_s3_bucket'
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
new_file_b64 = request.form['b64file']
if new_file_b64:
# Decode the image
new_file = base64.b64decode(new_file_b64)
# Crop the Image
img = Image.open(io.BytesIO(new_file))
img.thumbnail((200, 200))
# Tag this filename with an expiry time
future = datetime.utcnow() + timedelta(days=10)
timestamp = str(calendar.timegm(future.timetuple()))
filename = "thumb.%s.jpg " % timestamp
# Send the Bytes to S3
img_bytes = io.BytesIO()
img.save(img_bytes, format='JPEG')
s3_object = s3.Object(BUCKET_NAME, filename)
resp = s3_object.put(
Body=img_bytes.getvalue(),
ContentType='image/jpeg'
)
if resp['ResponseMetadata']['HTTPStatusCode'] == 200:
# Make the result public
object_acl = s3_object.Acl()
response = object_acl.put(
ACL='public-read')
# And return the URL
object_url = "https://{0}.s3.amazonaws.com/{1}".format(
BUCKET_NAME,
filename)
return object_url, 200
else:
return "Something went wrong :(", 400
return render_template('upload.html')
Unlike chalice, you can deploy WSGI application, so you can prepare a photo upload screen together.
You can also use the AWS event source to perform thumbnail processing non-blocking with uploading to S3 as a hook.
# zappa_settings.yml
---
dev:
app_function: your_project.main.app
events:
- function: your_project.users.thumbnailer
event_source:
arn: arn:aws:s3:::your_public_s3_bucket
events:
- s3:ObjectCreated:*
# your_project/users.py
import Pillow
def thumbnailer(event, context):
""" Upon PUT, thumbnail! """
# Get the bytes from S3
in_bucket = event['Records']['s3']['bucket']['name']
key = event['Records']['s3']['object']['key']
image_bytes = s3_client.download_file(in_bucket, key, '/tmp/' + key).read()
# Thumbnail it
size = (250, 250)
thumb = ImageOps.fit(image_bytes, size, Image.ANTIALIAS)
# Put it back on S3
s3_client.put_object(
ACL='public-read',
Body=thumb,
Key=key + 'thumbnail.jpg',
Bucket='avatar-bucket')
See Server-less Framework Comparison --Zappa Versus Chalice for more information.
Zappa seems to be number one in Top 10 Python libraries of 2016 --Tryolabs Blog In addition, as of December 2016, Zappa seems to be more popular than charice.
But as we've seen here, the two frameworks are distinct and distinct. I hope that the Python serverless framework area will become more exciting by using it properly according to the purpose.
Recommended Posts