Comparison of Python serverless frameworks-Zappa vs Chalice

Introduction

This article is the 23rd day of Serverless (2) Advent Calendar 2016.

Python serverless framework

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.

Referenced

in conclusion

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

Comparison of Python serverless frameworks-Zappa vs Chalice
Easily serverless with Python with chalice
Comparison of 4 Python web frameworks
Speed comparison of Python XML parsing
(Java, JavaScript, Python) Comparison of string processing
Comparison of matrix transpose speeds with Python
Introduction of Python
First Python 3 ~ First comparison ~
Performance comparison of face detector with Python + OpenCV
Python speed comparison regex vs startswith vs str [: word_length]
[Python3] Coarse graining of numpy.ndarray Speed comparison etc.
Basics of Python ①
Basics of python ①
Thorough comparison of three Python morphological analysis libraries
Copy of python
Simple comparison of Python libraries that operate Excel
Comparison of R and Python writing (Euclidean algorithm)
Comparison of Python and Ruby (Environment / Grammar / Literal)
Introduction of Python
[Ruby vs Python] Benchmark comparison between Rails and Flask
Python implementation comparison of multi-index moving averages (DEMA, TEMA)
Understand the status of data loss --Python vs. R
Comparison of CoffeeScript with JavaScript, Python and Ruby grammar
[Python] Operation of enumerate
Python SDP runtime comparison
Unification of Python environment
Copy of python preferences
Basics of Python scraping basics
[python] behavior of argmax
Comparison of LDA implementations
Comparison of online classifiers
Usage of Python locals ()
the zen of Python
Installation of Python 3.3 rc1
Comparison of fitting programs
# 4 [python] Basics of functions
Basic knowledge of Python
Sober trivia of python3
Python package manager comparison
Basics of python: Output
Installation of matplotlib (Python 3.3.2)
Application of Python 3 vars
Various processing of Python
Comparison of exponential moving average (EMA) code written in Python
Comparison of data frame handling in Python (pandas), R, Pig