Update: After receiving some feedback, that it is not obvious if you need to use Python 2 or 3 for this article, I decided, that I want to update it all the way for Python 3. AWS Lambda supports it, Zappa supports it and we all want Python 3!

I wanted to try out AWS Lambda for a while now. But it took some time to find a reasonable development task that fits this infrastructure. Serverless deployment is very intriguing, escpecially for someone like me that doesn’t enjoy to fiddle with servers, operating systems and stuff.

No, I won’t reveal any detals about my project yet. But I want to share my experiences building a simple webapp – the good old hello world example – and deploy it on AWS Lambda.

Lambda functions can be created using Python, node, Java and C# at the moment. (Take a look at the document about the supported execution environments.) Obviously my choice is Python.

And as I plan to deploy a whole web application and not just a simple function, I need some more incredients to build it.

  • Zappa – A framework to easily build and deploy serverless web services with Python.
  • Flask – The other awesome web framework for Python besides Django. For the project I have in mind, it seems to be the better choice. And I wanted to build something with Flask anyway.
  • awscli – The AWS Command Line Interface (CLI) is a unified tool to manage your AWS services.

Step 1: Set up the Python environment

I assume, that you are using macOS and Homebrew is installed on your development machine. Currently I am a big fan of pipenv to manage project dependencies and the virtual environment for projects.

Open a terminal and execute the following commands. Afterwards we have a nice and clean Python installation along with some essential tools.

# install python
brew update
brew install python3

# install and upgrade some essential packages
pip install --upgrade pip setuptools pipenv

# optionally install some handy development tools
pip install flake8 autopep8 ipython cookiecutter

If you are running Windows or Linux, you need to configure the Python environment on your own.

Step 2: Setup the project and create the web application

In this step we will setup our new project and create the trivial web application. First, we have to execute some shell commands to create our new project.

# create an empty directory for our project
mkdir lambda-hello-world
cd lambda-hello-world

# Init the Pipfile and a virtual environment for the project.
pipenv --three

# activate the virtual environment
pipenv shell

# install Zappa and Flask along with the AWS command line tools
pipenv install zappa flask
pipenv install --dev awscli

# optionally install some handy development tools inside the virtual environment
pipenv install --dev flake8 autopep8 ipython

Next we create a file named hello_world.py inside the directory lambda-hello-world with the following content. Nothing tricky, just a trivial Flask web application to return the string “Hello, world!”.

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    return "Hello, world!", 200

# We only need this for local development.
if __name__ == '__main__':
    app.run()

Finally, we can fire up our local debug server and test our simple web application.

export FLASK_APP=hello_world.py
flask run

You can reach it by opening the url http://127.0.0.1:5000/ in your browser.

Step 3: Configure your AWS credentials and default region

Before we deploy our web application, we have to make sure we have a valid AWS account and our AWS credentials and default region is properly configured on the development machine.

All this can be done with the AWS Command Line Tools as described in the document Configure the AWS command line interface. Basically we just have to run the command aws configure in our project directory and fill in the access key id, the secret access key and the default region.

Now our AWS account is setup on our development machine and we can start to configure Zappa and deploy our application to AW.

Step 4: Configure Zappa for our project

So far we have a setup our project, added a simple web application and configured our AWS account. Now, we can prepare our project to be managed and deployed by Zappa. In order to do this, we just have to run the following command inside the project directory.

zappa init

It creates a file named zappa_settings.json inside your project directory with the following content. That is all we need to deploy our app.

{
    "dev": {
        "app_function": "hello_world.app",
        "s3_bucket": "zappa-some-random-id",
"runtime": "python3.6"
    }
}

Of course Zappa offers a lot more configuration options for bigger projects.

Step 5: Deploy the web application

Last but not least, we can deploy the app and enjoy our simple, (extremly :))scalable “Hello , World!” application.

zappa deploy

What’s next?

Well, now it is about time to built something useful with this awesome stack. I really like how you can built fast and scalable web apps which access  a lot of other AWS services like Rekognition, DynamoDB and so on. You can expect some more blog posts out my adventures in Lambda land in the near future.


Image credit: Qfamily. Shared under the Creative Commons Attribution 2.0 Generic license.

About the Author Oliver Andrich

Developer – Web Aficionado – Part-Time Blogger

13 comments

  1. Thanks for this post, I found it helpful.

    One remark: maybe you could make it explicit that the project HAS to be setup using python 2.7… I set it up using 3.5 first, because from the way you wrote it it did not seem mandatory to use 2.7.

  2. Sorry for long post, but am banging my head against this, so any help much appreciated. Error at the bottom – top shows system details in case helpful. Any pointers at all would be well received!

    (venv) root@osmc:/opt/alexa-kodi/kodi-alexa-master/venv/bin# uname -a
    Linux osmc 4.4.27-9-osmc #1 SMP PREEMPT Tue Mar 14 20:54:19 UTC 2017 armv7l GNU/Linux

    (venv) root@osmc:/opt/alexa-kodi/kodi-alexa-master/venv/bin# which python
    /opt/alexa-kodi/kodi-alexa-master/venv/bin/python

    (venv) root@osmc:/opt/alexa-kodi/kodi-alexa-master/venv/bin# /opt/alexa-kodi/kodi-alexa-master/venv/bin/python -V
    Python 3.4.2

    (venv) root@osmc:/opt/alexa-kodi/kodi-alexa-master/venv/bin# which zappa
    /opt/alexa-kodi/kodi-alexa-master/venv/bin/zappa

    (venv) root@osmc:/opt/alexa-kodi/kodi-alexa-master/venv/bin# zappa -v
    0.42.0

    (venv) root@osmc:/opt/alexa-kodi/kodi-alexa-master/venv/bin# more zappa_settings.json
    {
    “dev”: {
    “app_function”: “alexa.app”,
    “aws_region”: “eu-west-1”,
    “profile_name”: “default”,
    “s3_bucket”: “BUCKET_ID_REMOVED ”
    }
    }

    (venv) root@osmc:/opt/alexa-kodi/kodi-alexa-master/venv/bin# zappa deploy
    Calling deploy for stage dev..
    Oh no! An error occurred! 😦

    ==============

    Traceback (most recent call last):
    File “/usr/lib/python3.4/distutils/dir_util.py”, line 70, in mkpath
    os.mkdir(head, mode)
    FileExistsError: [Errno 17] File exists: ‘/tmp/1495702120/gunicorn’

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
    File “/opt/alexa-kodi/kodi-alexa-master/venv/lib/python3.4/site-packages/zappa/cli.py”, line 2353, in handle
    sys.exit(cli.handle())
    File “/opt/alexa-kodi/kodi-alexa-master/venv/lib/python3.4/site-packages/zappa/cli.py”, line 456, in handle
    self.dispatch_command(self.command, stage)
    File “/opt/alexa-kodi/kodi-alexa-master/venv/lib/python3.4/site-packages/zappa/cli.py”, line 490, in dispatch_command
    self.deploy()
    File “/opt/alexa-kodi/kodi-alexa-master/venv/lib/python3.4/site-packages/zappa/cli.py”, line 650, in deploy
    self.create_package()
    File “/opt/alexa-kodi/kodi-alexa-master/venv/lib/python3.4/site-packages/zappa/cli.py”, line 1945, in create_package
    output=output
    File “/opt/alexa-kodi/kodi-alexa-master/venv/lib/python3.4/site-packages/zappa/core.py”, line 480, in create_lambda_zip
    copy_tree(temp_package_path, temp_project_path, update=True)
    File “/usr/lib/python3.4/distutils/dir_util.py”, line 168, in copy_tree
    verbose=verbose, dry_run=dry_run))
    File “/usr/lib/python3.4/distutils/dir_util.py”, line 141, in copy_tree
    mkpath(dst, verbose=verbose)
    File “/usr/lib/python3.4/distutils/dir_util.py”, line 74, in mkpath
    “could not create ‘%s’: %s” % (head, exc.args[-1]))
    distutils.errors.DistutilsFileError: could not create ‘/tmp/1495702120/gunicorn’: File exists

    ==============

    Need help? Found a bug? Let us know! 😀
    File bug reports on GitHub here: https://github.com/Miserlou/Zappa
    And join our Slack channel here: https://slack.zappa.io
    Love!,
    ~ Team Zappa!

    1. (the file does exist, but each time I run this, it creates a new one, owned by root, e.g.
      -rwxr-xr-x 1 root root 257 May 25 08:28 /tmp/1495702120/gunicorn

      1. Having spent hours on this, I think I spotted the mistake within seconds of posting here. I’m running as root. Something seems unhappy with this, as I’m getting more useful errors when running as a less-privileged user. Sorry for the bother, I hope this helps someone else

  3. Hey Oliver, I have browsing for a long time for easy to understand Zappa intro tutorial for a python beginner like me and your blog has been the most helpful. I loved the way you simplified the learning. Thanks a ton!

  4. Hi there. Thanks for the tutorial, I found it useful. Just thought I’d mention that using Homebrew 1.2.4 on macOS Sierra 10.12.5, python3 gets installed as…. python3, with pip installed as pip3.

    Thus if I were to copy and paste your example commands it would all be using python 2.7, which I believe is not what you want here. (I will probably add an alias as I don’t think I really need python 2.7 for anything, I’m just building Lambda apps.)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s