<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Adam Johnson</title>
    <description>The latest articles on DEV Community by Adam Johnson (@adjohn).</description>
    <link>https://dev.to/adjohn</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F56180%2Fa3e19455-52b2-4475-98bf-65ef2826dd97.png</url>
      <title>DEV Community: Adam Johnson</title>
      <link>https://dev.to/adjohn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adjohn"/>
    <language>en</language>
    <item>
      <title>Optimizing AWS Java Lambdas</title>
      <dc:creator>Adam Johnson</dc:creator>
      <pubDate>Wed, 31 Oct 2018 17:01:19 +0000</pubDate>
      <link>https://dev.to/adjohn/optimizing-aws-java-lambdas-4kmo</link>
      <guid>https://dev.to/adjohn/optimizing-aws-java-lambdas-4kmo</guid>
      <description>&lt;p&gt;&lt;em&gt;This was originally authored by &lt;a href="https://twitter.com/multiphasicapps" rel="noopener noreferrer"&gt;Stephanie Gawroriski (Xer)&lt;/a&gt; on the &lt;a href="https://read.iopipe.com/optimizing-aws-java-lambdas-3ea2b872fe74" rel="noopener noreferrer"&gt;IOpipe blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If your Java lambdas are running slow, it can be a nightmare to find the culprit! This article will cover a bunch of tried and true tips that you can utilize to optimize your code so that it runs faster, or uses less memory.&lt;/p&gt;

&lt;p&gt;There are many optimization techniques that you can use and some will work better than others depending on the situation. In this article we will concentrate on optimizations that can improve your Java AWS Lambda functions.&lt;/p&gt;

&lt;h1&gt;
  
  
  Finding which parts of the function are slow
&lt;/h1&gt;

&lt;p&gt;The most important thing when optimizing is to know where to optimize. This is something a profiler can help you with; it can tell you, in extremely granular detail, all of the potentially problematic regions of your code in terms of performance.&lt;/p&gt;

&lt;p&gt;Note that profiler data might not always be precise and sometimes that imprecision might misrepresent situations, so they should really be used as a pointer in the direction of code that needs to be optimized. It is an available tool and one that can be very important when you look at the performance of your own code.&lt;/p&gt;

&lt;p&gt;Of course, you are not required to use profiler, you could potentially measure how long execution takes by using &lt;code&gt;System.nanoTime()&lt;/code&gt; at the start and end of a block of code. That would naturally just be a simple metric and it would have far less overhead than using a full-fledged profiler.&lt;/p&gt;

&lt;p&gt;Doing this may help you concentrate on only a certain portion of code rather than seeing all of the data that represents all of your code. It might be very primitive but, like debugging messages made by &lt;code&gt;System.err.printf()&lt;/code&gt;, it is quick and easy to add and the only thing you will be given is the information you specifically ask for. You could even use a combination of this with profiling to give you a better idea of what is happening with your code, and with &lt;code&gt;printf()&lt;/code&gt; you may find this situation only happens under certain circumstances — profilers generally do not contain any information about the input for a method, so they lack some context.&lt;/p&gt;

&lt;h1&gt;
  
  
  The First Place to Look: The Algorithm
&lt;/h1&gt;

&lt;p&gt;No matter which optimization you plan on performing, the first factor to check is whether the algorithms you are using in your code are optimal. Improvements in the algorithm used will in many cases outweigh the other optimizations that you perform on your code, saving time and money.&lt;/p&gt;

&lt;p&gt;For example, if you were sorting numbers or other entries passed by a user, then you will need to choose a sorting algorithm. Algorithms such as selection sort will be slow, while merge sort will perform better. If you spend your time optimizing selection sort then in most cases even the mostly badly written merge sort will probably still run faster than your lean and fast selection sort.&lt;/p&gt;

&lt;h1&gt;
  
  
  Reducing the complexity of your classes
&lt;/h1&gt;

&lt;p&gt;There was a lot of discussion of this solution in my previous article &lt;a href="https://read.iopipe.com/java-libraries-are-your-lambda-enemy-6c9467321d2b?utm_source=devto&amp;amp;utm_campaign=java_lambda_optimization_post" rel="noopener noreferrer"&gt;Java Libraries are Your Lambda Enemy&lt;/a&gt;. When a class is initialized by the virtual machine, it parses the class and needs to load all the information for the class, however this is in itself not a complex process. The complexity generally comes from the JIT compiler needing to compile all the code so it runs faster in the virtual machine. However a large number of simple classes can slow this process down because the virtual machine needs to handle far more classes; especially when there are many class dependencies. So you should keep your class complexity down and the number of classes down.&lt;/p&gt;

&lt;p&gt;This feels like an obvious solution — fewer classes means less for the virtual machine to do. But it’s easy to accidentally add what seem like small libraries that turn out to need many dependencies. One thing to be particularly aware of is &lt;code&gt;ServiceLoader&lt;/code&gt;— any classes which are discovered by the service loader will be initialized when they are iterated through. So this means that services that you might not ever use might just get initialized. If you need to use the service loader to discover services then those service class implementations should be simple factory classes.&lt;/p&gt;

&lt;h1&gt;
  
  
  Initializing variables and classes when needed and using the cache
&lt;/h1&gt;

&lt;p&gt;This is something that varies, but usually the practice on normal servers is to initialize all you can when the program starts. Since the processes are more long lived these steps are done at the start so they never really become a problem in the long run. However in the Lambdas, with the massive contention during cold starts, the time spent initializing every single variable will be costly and cut into your initial cold start which may potentially time out or not be fast enough to where it overwhelms the lambda.&lt;/p&gt;

&lt;p&gt;So to put less pressure on the cold start you should instead opt to initialize data only when it is needed. That way any complex data is only initialized as it is needed.&lt;/p&gt;

&lt;p&gt;If your class generates any other objects which are used on an as-needed basis, if they are not required at all times then you can use a cache to keep it in memory for awhile. If you can recycle the cached objects you will save on initialization time for that class.&lt;/p&gt;

&lt;p&gt;The proper way to implement this cache is to use &lt;code&gt;SoftReference&amp;lt;T&amp;gt;&lt;/code&gt;, this reference will keep pointing to the object until there are no strong references to it (fields and variables) and when memory has been exhausted (during garbage collection). If you need to know when the reference is cleared then you can use &lt;code&gt;ReferenceQueue&amp;lt;T&amp;gt;&lt;/code&gt;; note that this uses polling which can either return immediately or wait until an object is made available and as such if a queue is used it will likely best be placed in its own thread.&lt;/p&gt;

&lt;h1&gt;
  
  
  Avoid blocking
&lt;/h1&gt;

&lt;p&gt;One of the worst things you can do in your code when it has to have a low latency is blocking. This blocking happens when you wait for data in another thread ( &lt;code&gt;synchronized&lt;/code&gt;, &lt;code&gt;Object.wait()&lt;/code&gt;, and &lt;code&gt;Lock.lock()&lt;/code&gt;) or when you are waiting for a result from a remote request (such as HTTP). Any time your program is just sitting around waiting for something to happen, is time spent wasted. Since only a single execution of a Lambda happens at once there will really be no benefit if the CPU is not being used at all because your cost is the same regardless of how much or how little CPU you use (if you &lt;code&gt;Thread.sleep()&lt;/code&gt; with a long duration that will cost you despite nothing happening).&lt;/p&gt;

&lt;p&gt;If it is possible in your code, one way to reduce the time spent blocking is to create a thread which works in the background, then when you actually need the result you could block until it is available. You can have a worker object which stores the result of the calculation and have within there an atomic type (such as &lt;code&gt;AtomicInteger&lt;/code&gt; or &lt;code&gt;AtomicObject&amp;lt;T&amp;gt;&lt;/code&gt;), read that value to see if one is available then if not lock on a monitor and then wait for a result to be calculated, reading in a loop and ignoring &lt;code&gt;InterupptedException&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Alternatively a more performative implementation would use &lt;code&gt;ReadWriteLock&lt;/code&gt; and &lt;code&gt;Condition&lt;/code&gt; to perform the same function (since lower level locks, despite requiring more implementation work, can perform better than &lt;code&gt;volatile&lt;/code&gt; and &lt;code&gt;synchronized&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Of course, if the thread has to run and finish but no result is needed, then it can just wait on a lock then once it is obtained it can just unlock and exit. Naturally if you want to avoid using locks and instead just constantly read from an atomic variable until some value is set, your busy loop should &lt;code&gt;Thread.yield()&lt;/code&gt; so that we can tell the operating system that we want to give up the rest of our CPU slice and give that to another thread. Yielding may or may not have an effect depending on the number of threads which can run at the same time in the container the lambda is running in, however if in the event there are not enough resources to run so many threads at once it will free up CPU slices so a thread which is actually doing something can do what it needs to do.&lt;/p&gt;




&lt;p&gt;Hopefully you find this information useful and can use it to help optimize your Lambdas so that they perform better, to lower your costs and allow you to serve requests faster.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>serverless</category>
      <category>java</category>
      <category>development</category>
    </item>
    <item>
      <title>The Right Way™ to do Serverless in Python (Part 2)</title>
      <dc:creator>Adam Johnson</dc:creator>
      <pubDate>Tue, 10 Jul 2018 19:58:03 +0000</pubDate>
      <link>https://dev.to/adjohn/the-right-way-to-do-serverless-in-python-part-2-3deg</link>
      <guid>https://dev.to/adjohn/the-right-way-to-do-serverless-in-python-part-2-3deg</guid>
      <description>&lt;p&gt;&lt;em&gt;Note: This article was authored by &lt;a href="https://github.com/kolanos"&gt;Michael Lavers&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://read.iopipe.com/the-right-way-to-do-serverless-in-python-e99535574454"&gt;Part 1&lt;/a&gt; we covered the serverless basics and got our feet wet with the Serverless Framework. If you haven't read that part yet, it's highly encouraged that you start there. Assuming you've followed along in Part 1, you now know how to create and deploy a simple AWS Lambda function in Python; including a web API using AWS API Gateway. But we've only just scratched the surface of what you can do in serverless with Python. In this post, we'll introduce a library that allows you to plug any web framework that speaks WSGI into serverless (pretty much all of them); and we'll take a look at AWS' own Python web framework for creating web APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Zappa
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.zappa.io"&gt;Zappa&lt;/a&gt;, named after the legendary Frank Zappa, is the original Python serverelss library/framework. It was originally conceived as django-zappa, a library to allow you to deploy Django web applications to AWS Lambda. It has since grown in leaps and bounds and now supports any WSGI compatible Python web framework. It has also expanded it's feature set and is very much a "batteries included" tool for creating, deploying and managing serverless web applications written in Python.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is WSGI?
&lt;/h3&gt;

&lt;p&gt;If you've done Python web development before, you've likely heard of WSGI. But what is it? WSGI stands for "Web Server Gateway Interface" and it's an implementation agnostic interface between web servers and web applications/frameworks. It was &lt;a href="https://www.python.org/dev/peps/pep-3333/"&gt;created by the Python community&lt;/a&gt; back in 2003 because there wasn't a standard way to develop a web application in Python back then. Instead you first had to pick a web server, which could use CGI, FastCGI, mod_python or something else entirely and develop against that. Which meant your web application was very much coupled to the web server in which it was built upon (remember Zope?). Now we have WSGI and all modern Python web frameworks support it, which means you can use whatever web server you like -- or no server at all? Yes, thanks to Zappa, WSGI is supported on serverless, too.&lt;/p&gt;

&lt;p&gt;The reason I refer to Zappa as a "library/framework" is that it kind of lives in both worlds. Zappa at it's core is a compatibility/translation layer between serverless and WSGI. For example, with AWS Lambda, Zappa takes the HTTP event we covered in Part 1 and converts it into a WSGI compatible equivalent representation that all WSGI web frameworks can use. This is where Zappa feels like a "library", but then Zappa packs a ton of useful features on top and starts to feel more like a "framework". Although, like WSGI, Zappa is very much agnostic when it comes to the actual web framework you use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which web framework should I use?
&lt;/h3&gt;

&lt;p&gt;If you're asking this question, then I would recommend you start with either &lt;a href="https://www.djangoproject.com"&gt;Django&lt;/a&gt; or &lt;a href="http://flask.pocoo.org"&gt;Flask&lt;/a&gt;. Django is the most popular web framework in Python and is very much a "batteries included" option. Flask is arguably the second most popular web framework in Python and calls itself a "micro framework"; it has a simpler API and doesn't come with all the bells and whistles that Django does. Both are excellent options and are very well documented. In this post, we'll focus on these two web frameworks when it comes to Zappa, but Zappa should work with pretty much &lt;a href="https://wiki.python.org/moin/WebFrameworks"&gt;any Python web framework&lt;/a&gt;. Suffice to say, if you're using Bottle, Pyramid, Tornado, Falcon or something else -- it should be easy to get your web application running on serverless using Zappa.&lt;/p&gt;

&lt;h3&gt;
  
  
  Django Meets Zappa
&lt;/h3&gt;

&lt;p&gt;As we mentioned in Part 1, the rule of thumb for new Python serverless projects is to use Python 3.6, and true to form, Django has &lt;a href="https://docs.djangoproject.com/en/2.0/releases/2.0/"&gt;dropped Python 2.7 support&lt;/a&gt; in Django 2.0. This may seem like a sad day for all the Python 2.7 loyalists out there, but the pros greatly outweigh the cons here. Think about it: no more &lt;a href="https://pythonhosted.org/six/"&gt;six&lt;/a&gt;. That alone should put a smile on your face -- at least until Python 4 is released.&lt;/p&gt;

&lt;p&gt;Now before we dive into Zappa, we first need to create a Django web app. Django makes this really easy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-U&lt;/span&gt; django
django-admin startproject mydjangoapp
&lt;span class="nb"&gt;cd &lt;/span&gt;mydjangoapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will install the latest version of &lt;code&gt;django&lt;/code&gt; using &lt;code&gt;pip&lt;/code&gt; and the &lt;code&gt;django-admin startproject&lt;/code&gt; command will create a directory called &lt;code&gt;mydjangoapp&lt;/code&gt; with a preconfigured Django web app ready to go. Now if you've done Python web development before, you're likely asking "what about the virtualenv?" If you don't know what a "virtualenv" is, it's a best practice in Python to create a "virtual environment" for each project so that all your dependencies remain in one place and don't get mixed up with other projects. There are a number of tools out there to make managing virtual environments easy. for example, the one gaining a lot of traction recently is Kenneth Reitz' &lt;a href="https://docs.pipenv.org"&gt;Pipenv&lt;/a&gt;. If you don't know who that is, he's the guy behind &lt;a href="http://docs.python-requests.org/en/master/"&gt;requests&lt;/a&gt;, you likely know his work. But I'm still partial to &lt;a href="http://virtualenvwrapper.readthedocs.io/en/latest/"&gt;virtualenvwrapper&lt;/a&gt; I'm going to treat virtual environments as a personal preference. It's still a best practice, though, so pick whichever tool fits your workflow the best.&lt;/p&gt;

&lt;p&gt;Now that we have a Django project created and we're in our &lt;code&gt;mydjangoapp&lt;/code&gt; directory let's fire up Zappa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-U&lt;/span&gt; zappa
zappa init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zappa is going to ask a series of questions about your web app. For now, you can stick with the defaults that Zappa suggests. As we mentioned in Part 1, like with the Serverless Framework, Zappa is going to check that your AWS credentials &lt;a href="https://aws.amazon.com/blogs/security/a-new-and-standardized-way-to-manage-credentials-in-the-aws-sdks/"&gt;are properly configured&lt;/a&gt;. If you have multiple AWS profiles configured, Zappa wil ask which one to use, but if you only have one, then the default is what you want. After running &lt;code&gt;zappa init&lt;/code&gt; and answering the questions, you'll find that Zappa has created a &lt;code&gt;zappa_settings.json&lt;/code&gt; file in your project directory. This file serves the same purpose as the &lt;code&gt;serverless.yml&lt;/code&gt; in Part 1, but because it is JSON there are no comments. Thankfully, Zappa &lt;a href="https://github.com/Miserlou/Zappa#advanced-settings"&gt;documents&lt;/a&gt; the available settings. &lt;/p&gt;

&lt;p&gt;Now to deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zappa deploy dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Zappa will perform steps similar to Serverless Framework covered in Part 1, but out-of-the-box it will do some handy Python-specific things like sort out dependencies for us. Once it is done deploying, you should see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Deployment &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;: https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you've read Part 1 this is going to look familiar. It's a URL provided by AWS API Gateway. Let's open it up in a browser and see what we get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DisallowedHost at /

Invalid HTTP_HOST header: 'xxxxxxxxxx.execute-api.us-east-1.amazonaws.com'. You may need to add 'xxxxxxxxxx.execute-api.us-east-1.amazonaws.com' to ALLOWED_HOSTS.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Huh. Ok, let's do that. Open up &lt;code&gt;mydjangoapp/settings.py&lt;/code&gt; and look for the &lt;code&gt;ALLOWED_HOSTS&lt;/code&gt; setting and change it to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ALLOWED_HOSTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;".execute-api.us-east-1.amazonaws.com"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why aren't we including the &lt;code&gt;xxxxxxxxxx&lt;/code&gt; part? Well, this part of the hostname is prone to change. For example, if you decide to deploy a staging or production environment with Zappa, then this part of the hostname is going to be different. Setting your &lt;code&gt;ALLOWED_HOSTS&lt;/code&gt; this way allows you to support every environment you deploy with Zappa in AWS &lt;code&gt;us-east-1&lt;/code&gt;. If you decide to deploy in another AWS region, then you'll need to update your &lt;code&gt;ALLOWED_HOSTS&lt;/code&gt; accordingly. Let's save and re-deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zappa update dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice here the command is &lt;code&gt;zappa update&lt;/code&gt; and not &lt;code&gt;zappa deploy&lt;/code&gt;. This is because most of your serverless web app is already deployed. All we need to do now is replace our package in the S3 bucket Zappa created for us. You should notice that &lt;code&gt;zappa update&lt;/code&gt; runs noticeably faster. Once done, let's reload our &lt;code&gt;https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev&lt;/code&gt; URL in a browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Page not found  (404)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ok, we're making progress. The reason we're getting a "Page Not Found" error is that Django doesn't configure a page for &lt;code&gt;/&lt;/code&gt; by default. Let's fix that. First, we'll need to create a Django app in our project. A Django web application is comprised of "apps". Say your web application had a blog and a store, each of those would be an "app" in your Django project. To create an app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python manage.py startapp myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will create a &lt;code&gt;myapp&lt;/code&gt; directory in your project. Inside that directory are a handful of modules to support an app. But before we start working on our app we must first register it within our Django project. To do this, we need to open our &lt;code&gt;mydjangoapp/settings.py&lt;/code&gt; again and look for the &lt;code&gt;INSTALLED_APPS&lt;/code&gt; setting. There we want to add our app to the end of the list, so it should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;INSTALLED_APPS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="s"&gt;'myapp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that &lt;code&gt;INSTALLED_APPS&lt;/code&gt; will have several Django apps already installed. We want to keep those and just add a new app to the list. So the &lt;code&gt;....&lt;/code&gt; represents all the Django apps that are already configured. Save this file and open up &lt;code&gt;mydjangoapp/urls.py&lt;/code&gt;. This file is where Django configures all the routes of our web application. In fact, if you notice, there's already a route configured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'admin/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Interesting. What if we open &lt;code&gt;https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev/admin/&lt;/code&gt; in a browser? How about that. The Django admin app is already there running. Unfortunately we haven't configured any users in our Django project, so we won't be able to get beyond this login page. Back to what we were originally doing. Let's add a route for &lt;code&gt;/&lt;/code&gt; and serve up an HTML template. First we'll need to import Django's &lt;code&gt;TemplateView&lt;/code&gt;. After the &lt;code&gt;from django.urls import path&lt;/code&gt; line, add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;django.views.generic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TemplateView&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then update our &lt;code&gt;urlpatterns&lt;/code&gt; like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'admin/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TemplateView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;template_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'index.html'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we're configuring an empty route, which is equivalent to &lt;code&gt;/&lt;/code&gt; which is to be served by &lt;code&gt;TemplateView&lt;/code&gt; using a &lt;code&gt;template_name&lt;/code&gt; of &lt;code&gt;index.html&lt;/code&gt;. Now to create the template, we need to go back to our app. From our project directory, we create a &lt;code&gt;templates&lt;/code&gt; directory in our app and add a template to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;myapp/templates
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;h1&amp;gt;Hello Django&amp;lt;/h1&amp;gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; myapp/templates/index.html
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the template's name is &lt;code&gt;index.html&lt;/code&gt; like we specified in our &lt;code&gt;urls.py&lt;/code&gt;. Django will automatically load any templates it finds in any of the &lt;code&gt;INSTALLED_APPS&lt;/code&gt;, assuming a &lt;code&gt;templates&lt;/code&gt; directory is present for that app. Now re-deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zappa update dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And reload &lt;code&gt;https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev&lt;/code&gt; in a web browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Hello Django
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And  just like that you have a serverless Django web app. Zappa truly couldn't make it any easier. Deploying the same app to a regular web server would actually be more work. Aren't you glad you ditched those things?&lt;/p&gt;

&lt;p&gt;Now as cool as a stock Django app running on serverless is, if we refer back to Part 1, we're really looking to build a web API and workers, right? With Django, we're in luck, as it has one of the most powerful and well-documented REST frameworks out there called &lt;a href="http://www.django-rest-framework.org"&gt;Django REST Framework&lt;/a&gt;. And if you follow the &lt;a href="http://www.django-rest-framework.org/#installation"&gt;installation instructions&lt;/a&gt; you'll have a fully-featured REST API running on serverless in no time. Or if you're building a GraphQL API, then the excellent &lt;a href="https://github.com/graphql-python/graphene-django"&gt;Graphene&lt;/a&gt; integrates with Django.&lt;/p&gt;

&lt;p&gt;As for workers, Zappa offers &lt;a href="https://github.com/Miserlou/Zappa#scheduling"&gt;a solution&lt;/a&gt; not unlike the one we described in Part 1. If you had a function called &lt;code&gt;scheduled_job&lt;/code&gt; in &lt;code&gt;myapp/tasks.py&lt;/code&gt; that you wanted to execute every ten minutes, you would open your &lt;code&gt;zappa_settings.json&lt;/code&gt; and add the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"events"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"function"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"myapp.tasks.scheduled_job"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"expression"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"rate(10 minutes)"&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;```&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;endraw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;span class="err"&gt;And&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;then&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;deploy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;it:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;raw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;%&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;span class="err"&gt;```bash&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;zappa&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;schedule&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;dev&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you're good to go. And what about custom domains? Zappa &lt;a href="https://github.com/Miserlou/Zappa#deploying-to-a-domain-with-aws-certificate-manager"&gt;has you covered&lt;/a&gt; there, too. Before we continue, assuming you don't need this app, Zappa makes it easy to clean up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zappa unschedule dev
zappa undeploy dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Want to learn more about Django? Check out the &lt;a href="https://docs.djangoproject.com/en/2.0/"&gt;Django documentation&lt;/a&gt;. Or even better, check out these &lt;a href="https://docs.djangoproject.com/en/2.0/intro/"&gt;Django tutorials&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Flask Meets Zappa
&lt;/h3&gt;

&lt;p&gt;Now if the Django setup wasn't straightforward enough, Flask might be even easier. Assuming we're starting from a new virtualenv (see Django section for suggested tools for creating a virtualenv). We first install Flask and Zappa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-U&lt;/span&gt; flask zappa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create a project directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;myflaskapp
&lt;span class="nb"&gt;cd &lt;/span&gt;myflaskapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And within that directory add a &lt;code&gt;app.py&lt;/code&gt; with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'hi there'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then fire up Zappa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zappa init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like with our Django app, Zappa will auto-detect that our app is using Flask. And to deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zappa deploy dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we should get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Deployment &lt;span class="nb"&gt;complete&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;: https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to test it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which should return:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"message": "hi there"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Talk about an instant web API. So what's happening here? Zappa probably feels like magic, but it's really just clever. In Django, the WSGI is exposed in &lt;code&gt;mydjangoapp/wsgi.py&lt;/code&gt;. So Zappa creates a AWS Lambda handler for us that accepts HTTP requests. This handler transforms these requests into equivalent WSGI requests and passes them onto &lt;code&gt;mydjangoapp/wsgi.py&lt;/code&gt;. With Flask, it's pretty much the same idea. The only difference is that Flask exposes it's WSGI via the &lt;code&gt;app.run()&lt;/code&gt; method in our &lt;code&gt;app.py&lt;/code&gt; above.&lt;/p&gt;

&lt;p&gt;The Zappa topics we've covered already with Django are applicable to Flask as well. From scheduled jobs to custom domains, they're all supported.&lt;/p&gt;

&lt;p&gt;Want to learn more about Flask? Check out the &lt;a href="http://flask.pocoo.org/docs/1.0/"&gt;Flask documentation&lt;/a&gt;. Or even better, check out this &lt;a href="https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world"&gt;Flask mega tutorial&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Oh, and don't forget to clean up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zappa undeploy dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  More Zappa?
&lt;/h3&gt;

&lt;p&gt;In this post, we've only scratched the surface of what you can do with Zappa. Check out the &lt;a href="https://github.com/Miserlou/Zappa"&gt;Zappa documentation&lt;/a&gt; for more, including how to rollback deployments, tail logs, keep your functions warm, fire asynchronous jobs, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chalice
&lt;/h2&gt;

&lt;p&gt;If Zappa didn't inspire you to start building a serverless Python web app, I don't know what will, but it also appears to have inspired (at least in part) a team at AWS to start their own web framework specifically built for AWS Lambda. They call it &lt;a href="https://github.com/aws/chalice"&gt;Chalice&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This project is interesting for a couple reasons. First is that it is one of the few Python web frameworks out there that doesn't implement WSGI. While I've been waxing poetic on the virtues of WSGI, Chalice is built specifically for AWS LAmbda, and as such doesn't need an abstraction layer like WSGI. The trade off here is simplicity for lock in: the Chalice implementation is simplified by only having to target AWS LAmbda, but that also means you can only use Chalice with AWS Lambda. Second, Chalice's API is clearly influenced by another web framework we've already covered in this post, which helps with the learning curve. Which one you ask? Let's take a look.&lt;/p&gt;

&lt;p&gt;Assuming we're starting with a fresh virtualenv, install Chalice with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-U&lt;/span&gt; chalice
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And to create a project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;chalice new-project mychaliceapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command creates a directory called &lt;code&gt;mychaliceapp&lt;/code&gt; with a pre-configured Chalice project. Inside there's a &lt;code&gt;.chalice&lt;/code&gt; hidden directory that contains config files, a &lt;code&gt;requirements.txt&lt;/code&gt; and an &lt;code&gt;app.py&lt;/code&gt;. There's our first clue, if you recall, in our Flask app we created a &lt;code&gt;app.py&lt;/code&gt; as well, which is a common Flask idiom. But if we take a look at the &lt;code&gt;app.py&lt;/code&gt; it will become clear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;chalice&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Chalice&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Chalice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'mychaliceapp'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'hello'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'world'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look familiar? They say imitation is the sincerest form of flattery. And if I'm Armin Ronacher (creator of Flask), I'm feeling pretty flattered. And to deploy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;chalice deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the deploy finishes, Chalice will return a URL that should be familiar by now: &lt;code&gt;https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/api&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You guessed it, there's our old friend, API Gateway. And to test it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which should return:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"hello": "world"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We didn't even have to write any code for that one. Does that make it codeless as well?&lt;/p&gt;

&lt;p&gt;Chalice offers a Flask-esque API and is very much designed for JSON REST APIs. It also comes bundled with some nice integrations with other AWS services, including authentication with AWS Cognito. It is clear that the project is focused on the problem they're trying to solve, as such, as long as your problem is JSON REST APIs then Chalice can help you get up and running on AWS Lambda quickly. Anything else? You're going to want to look at the other options we've covered so far.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Summation
&lt;/h2&gt;

&lt;p&gt;In this post, we've taken a look a two Python tools looking to make developing, deploying and managing serverless apps easier. One that is agnostic as to what web framework you use, the other is very much opinionated. One thing is clear, the Python community is getting a lot right when it comes to serverless.&lt;/p&gt;

&lt;p&gt;In Part 3 we're going to compare and contrast all the options available in the serverless space for Python web apps. We'll also introduce you to a serverless observability tool that will give you visibility into your serverless web apps like never before. Stay tuned.&lt;/p&gt;

</description>
      <category>python</category>
      <category>django</category>
      <category>aws</category>
      <category>serverless</category>
    </item>
    <item>
      <title>The Right Way™ to do Serverless in Python (Part 1)</title>
      <dc:creator>Adam Johnson</dc:creator>
      <pubDate>Thu, 28 Jun 2018 20:55:07 +0000</pubDate>
      <link>https://dev.to/adjohn/the-right-way-to-do-serverless-in-python-part-1-353o</link>
      <guid>https://dev.to/adjohn/the-right-way-to-do-serverless-in-python-part-1-353o</guid>
      <description>

&lt;p&gt;&lt;em&gt;Note: This article was authored by &lt;a href="https://github.com/kolanos"&gt;Michael Lavers&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As you've undoubtedly heard, serverless has grown in leaps and bounds since the release of AWS Lambda in November 2013. And while the idea of not having to manage a server, paying only for the compute you actually use and horizontal scaling out-of-the box may sound really appealing, where do you start? As a Python developer, maybe you've heard of the &lt;a href="https://serverless.com"&gt;Serverless Framework&lt;/a&gt; or &lt;a href="https://www.zappa.io"&gt;Zappa&lt;/a&gt;; and either the prospect of working with an unfamiliar ecosystem like Node.js (in Serverless' case) is daunting, or maybe you're unclear on what these tools actually do and if they're overkill when you're just getting started. If that's the case, you've come to the right place. In this blog post we'll take a brief tour of serverless as it applies to Python as well as some handy tips and tricks to help you get your feet wet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is my app/workload right for serverless?
&lt;/h2&gt;

&lt;p&gt;This is probably the most important question you need to ask about serverless. While serverless has a lot to offer, it isn't ideal for all apps/workloads. For example, the current maximum duration for an AWS Lambda function invocation is five minutes. What this means is that if your app/workload can't be broken up into five minute chunks, then serverless might not be the best option. If your app uses websockets, for example, which maintains a persistent connection with the server, on AWS Lambda this connection would be closed and need to be reestablished every five minutes. It would also mean you're paying for all that compute time for a workload that is really just keeping a socket open. But if your app is mostly stateless, like a REST or GraphQL API, then serverless may be a great fit, as HTTP requests rarely go beyond 30 seconds, let alone five minutes.&lt;/p&gt;

&lt;p&gt;Where serverless really shines is workloads where you might have spikes and/or periods of low activity. If you think about it, that description likely applies to most apps/workloads you've worked on. When your app/workload spikes, then AWS Lambda is there to provide considerable horizontal scaling, by default handling 1,000 concurrent requests out-of-the-box (this limit can be increased). And when your app/workload is in a low activity period, your meter isn't running at full tilt, which can save you a lot on operating expenses. Think about it; most apps/workloads serve a range of timezones, so why should you pay full price to run your app/workload when your customers are asleep?&lt;/p&gt;

&lt;p&gt;If you're still not sure whether or not your app/workload is a good fit, here's a &lt;a href="https://servers.lol"&gt;handy calculator&lt;/a&gt; to compare AWS Lambda to EC2. &lt;/p&gt;

&lt;h2&gt;
  
  
  Python 2 or 3?
&lt;/h2&gt;

&lt;p&gt;The Python ecosystem has gone through a lot of changes the past decade -- the most significant being the release of Python 3 and the transition of many codebases from Python 2.x to 3.x. In the serverless world, the advice here is consistent with any other Python project: use Python 3.6 if it's a new project. While Python 2.7 has served many of us well, it will &lt;a href="https://pythonclock.org"&gt;cease to receive updates&lt;/a&gt; after 2020. So if you haven't already started your transition to 3.6, you have two years to do so.&lt;/p&gt;

&lt;p&gt;If you have an existing Python 2.7 project, you're in luck, as AWS Lambda supports 2.7, but you should seriously consider starting to port your code to Python 3.6 soon. Here's a super helpful &lt;a href="http://python-future.org/compatible_idioms.html"&gt;cheatsheet&lt;/a&gt; on how to write Python2+3 compatible code. And like the cheat sheet, the advice here will be 2.7/3.6 compatible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Web API or Worker?
&lt;/h2&gt;

&lt;p&gt;Before we go over the serverless tools available to Python, lets drill down a little more into our app/workload. If you have a web app that serves a front-end with several web assets (HTML, JavaScript, CSS, images, etc.), then you should not be serving these up via your AWS Lambda function. That's &lt;em&gt;not to say that you can't, just that you shouldn't&lt;/em&gt;. Remember that with AWS Lambda you pay for the time your function is running. It doesn't make much sense to spend this time serving up web assets. In fact, since your front-end likely has many web assets, this could be a relatively expensive way of doing what is otherwise a simple task. For serving up web assets, you should look at a CDN (Content Delivery Network). AWS has a service specifically built for this purpose called CloudFront, here's &lt;a href="https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/DownloadDistS3AndCustomOrigins.html"&gt;a guide&lt;/a&gt; on how to use it with S3.&lt;/p&gt;

&lt;p&gt;But that really only covers your web app's front-end. Or maybe your app/workload doesn't have a front-end at all. We're going to break these workloads into two categories: web APIs (REST, GraphQL, etc.), and workers. You're likely already familiar with the web API variety, and AWS Lambda allows us to serve them using a service called API Gateway (more on that later). The other, what I'm going to call "workers," is all the other tasks your app might need to do, such as: sending email, uploading files, push notifications, etc. Serverless can handle this workload, and even offers it's own cron job like service to handle scheduled tasks.&lt;/p&gt;

&lt;p&gt;The reason I'm defining these two categories is that while in serverless these workloads may look similar (or indistinguishable, as they're both essentially functions), some tools are better at or designed for one over the other. In this guide, I'll point out where this is the case. Hopefully you're already thinking about what parts of your app will be served via a web API and what parts can be worker tasks run in the background so you can pick the right tool for the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Serverless Framework
&lt;/h2&gt;

&lt;p&gt;The big kahuna in the serverless space is undoubtedly the &lt;a href="https://serverless.com"&gt;Serverless Framework&lt;/a&gt;, and for good reason. The team behind it has poured considerable time and effort into developer experience to make it one of the most intuitive and accessible serverless tools out there. It also offers a feature set that is second to none, supporting multiple clouds in addition to AWS Lambda and a growing plugin ecosystem. For a Python developer, this would seem like the obvious starting point and it certainly is a great one.&lt;/p&gt;

&lt;p&gt;But serverless framework is not without some Python-specific caveats. For starters, Serverless is written in Node.js, which may not be your cup of tea. But like any good tool, if done right, you shouldn't even notice what language it is implemented in, and the case could certainly be made here for Serverless. That being said, you'll still need to &lt;a href="https://nodejs.org/en/download/"&gt;install Node and NPM&lt;/a&gt;, but after that you're only a &lt;code&gt;npm install -g serverless&lt;/code&gt; away from having the Serverless CLI be your primary interface. You won't need to know any JavaScript, although your configs will be YAML by default.&lt;/p&gt;

&lt;p&gt;Let's give it a try.&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; serverless
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The CLI can be accessed using either &lt;code&gt;serverless&lt;/code&gt; or the shorthand &lt;code&gt;sls&lt;/code&gt;. I prefer &lt;code&gt;sls&lt;/code&gt;, so lets create a project:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/my-serverless-project
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/my-serverless-project
sls create &lt;span class="nt"&gt;-n&lt;/span&gt; my-serverless-project &lt;span class="nt"&gt;-t&lt;/span&gt; aws-python3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here I've created a directory called &lt;code&gt;my-serverless-project&lt;/code&gt; and created a project using &lt;code&gt;sls create&lt;/code&gt;. I'm also specifying a template with &lt;code&gt;-t aws-python3&lt;/code&gt;. Serverless comes bundled with several templates that will set some sensible defaults for you in your &lt;code&gt;serverless.yml&lt;/code&gt; that will be created when you run &lt;code&gt;sls create&lt;/code&gt;. In this case, I'm specifying the AWS template for Python 3.6. There's also a &lt;code&gt;aws-python2&lt;/code&gt; if you're project is Python 2.7. There are other templates for other languages and clouds, but that's outside of the scope of this guide. The &lt;code&gt;-n my-serverless-project&lt;/code&gt; specifies a service name, you can change this to whatever you want to name your project. Once you run these commands you should have a &lt;code&gt;serverless.yml&lt;/code&gt; in your &lt;code&gt;my-serverless-project&lt;/code&gt; directory. Let's take a look at the contents:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;serverless.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As you will see the &lt;code&gt;serverless.yml&lt;/code&gt; is YAML and comes loaded with several helpful comments explaining each section of the config. At this point I recommend reading through these comments as it will be helpful later on. Once done, let's write a hello world equivalent of a lambda function:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"hi there"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And save that in our &lt;code&gt;my-serverless-project&lt;/code&gt; directory as &lt;code&gt;hello.py&lt;/code&gt;. The name &lt;code&gt;handler&lt;/code&gt; is just what lambda functions are commonly referred, you can name your functions whatever you like. Now that we have a function, let's make Serverless aware of it by adding it to our &lt;code&gt;serverless.yml&lt;/code&gt;. First open up your &lt;code&gt;serverless.yml&lt;/code&gt; and look for the &lt;code&gt;functions&lt;/code&gt; section. Then replace that section with the following:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;functions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;hello&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello.handler&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now save your &lt;code&gt;serverless.yml&lt;/code&gt;. To deploy this function, we'll need to make sure we have our &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html"&gt;AWS credentials configured&lt;/a&gt;. Assuming we're all good there, then just run the following:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;sls deploy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Deployment will take a little while. In short, here's the steps that Serverless is doing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creating a CloudFormation template based on the &lt;code&gt;serverless.yml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Compressing the CloudFormation template and your &lt;code&gt;hello.py&lt;/code&gt; into a zip archive&lt;/li&gt;
&lt;li&gt;Creating a S3 bucket and uploading the zip archive to it&lt;/li&gt;
&lt;li&gt;Executing the CloudFormation template, which includes configuring an AWS Lambda function and pointing it to the S3 zip archive&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You could do all of these steps manually, but why would you want to? When our deploy is complete, we can test it with the following command:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;sls invoke &lt;span class="nt"&gt;-f&lt;/span&gt; hello
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;-f hello&lt;/code&gt; is the name of the function we specified in our &lt;code&gt;serverless.yml&lt;/code&gt; file. The &lt;code&gt;sls invoke&lt;/code&gt; command invokes the function. A function invocation is a fancy word for calling the function. When we invoke this function, it should respond with:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"message"&lt;/span&gt;: &lt;span class="s2"&gt;"hi there"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If that's what you see, congratulations, you've just created your first AWS Lambda function. But this isn't terribly useful.? What if we wanted to do something a little more challenging, like making a HTTP request and returning the result. Let's create a new file called &lt;code&gt;httprequest.py&lt;/code&gt; and add the following:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://news.ycombinator.com/news"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Update the &lt;code&gt;functions&lt;/code&gt; section of your &lt;code&gt;serverless.yml&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;functions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;hello&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello.handler&lt;/span&gt;
  &lt;span class="na"&gt;httprequest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;httprequest.handler&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And re-deploy and invoke our new function:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;sls deploy
sls invoke &lt;span class="nt"&gt;-f&lt;/span&gt; httprequest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You should now see an &lt;code&gt;ImportError&lt;/code&gt;. This is because &lt;code&gt;requests&lt;/code&gt; is not installed. With AWS Lambda, we need to bundle any libraries we want to use with our function. We can do this a number of ways, with &lt;code&gt;pip&lt;/code&gt; we can run:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Don't run this just yet, keep reading&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;requests &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will install the &lt;code&gt;requests&lt;/code&gt; wheel (and it's dependencies) in our &lt;code&gt;my-serverless-project&lt;/code&gt; directory. But there's a catch. AWS Lambda runs on 64-bit Linux. And because &lt;code&gt;requests&lt;/code&gt; comes with dependencies that are compiled, if you're not running 64-bit Linux as well this copy of &lt;code&gt;requests&lt;/code&gt; you just installed won't run on AWS Lambda. So what do you do if you're running Mac OS? Or Windows? Or FreeBSD? Or, well, you get the picture.&lt;/p&gt;

&lt;p&gt;Serverless plugins (and Docker) to the rescue.&lt;/p&gt;

&lt;p&gt;Thankfully Serverless comes with a plugin ecosystem to fill in the gaps, and for Python,  packages with compiled code just happens to be one of those gaps. The relevant plugin here is aptly named &lt;a href="https://github.com/UnitedIncome/serverless-python-requirements"&gt;serverless-python-requirements&lt;/a&gt;, and to install it:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; serverless-python-requirements
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And add the following lines to the end of your &lt;code&gt;serverless.yml&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;serverless-python-requirements&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now right away this plugin enables &lt;code&gt;requirements.txt&lt;/code&gt; support. So instead of the &lt;code&gt;pip&lt;/code&gt; line above, we now just need to add a &lt;code&gt;requirements.txt&lt;/code&gt; file to our project directory and the next time we run &lt;code&gt;sls deploy&lt;/code&gt; the requirements will be installed and bundled automatically. Let's do that now:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"requests"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But we haven't solved our compilation problem yet. To do that we'll need to add a &lt;code&gt;custom&lt;/code&gt; section to our &lt;code&gt;serverless.yml&lt;/code&gt;. This section is where we can put our custom configuration options, but it's also where plugins look to for their own config options. Our new &lt;code&gt;custom&lt;/code&gt; section should look like this:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;custom&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pythonRequirements&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;dockerizePip&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;What this does is tell the &lt;code&gt;serverless-python-requirements&lt;/code&gt; plugin to compile the Python packages in a Docker container before bundling them in the zip archive to ensure they're compiled for 64-bit Linux. You'll also need to &lt;a href="https://docs.docker.com/install/"&gt;install Docker&lt;/a&gt; in order for this to work, but once done this plugin will handle the dependencies you define in your &lt;code&gt;requirements.txt&lt;/code&gt; file automatically. Pretty cool, huh?&lt;/p&gt;

&lt;p&gt;Now let's re-deploy and re-invoke our function:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;sls deploy
sls invoke &lt;span class="nt"&gt;-f&lt;/span&gt; httprequest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Even if you are running 64-bit Linux, this is way cleaner, don't you think?&lt;/p&gt;

&lt;p&gt;Now before we continue, you likely have a few questions. What are &lt;code&gt;event&lt;/code&gt;, &lt;code&gt;context&lt;/code&gt; and how is any of this useful to me?&lt;/p&gt;

&lt;p&gt;AWS Lambda functions are event-driven, so when you invoke a function, you're actually triggering an event within AWS Lambda. The first argument of your lambda function contains the event that triggered the function, which is represented within AWS Lambda as a JSON object, but what is passed to Python is a dict of that object. When you run &lt;code&gt;sls invoke -f hello&lt;/code&gt;, what is passed to the lambda function is an empty dict. But if it was an API request, it would contain the entire HTTP request represented as a dict. In other words, the &lt;code&gt;event&lt;/code&gt; dict acts as your lambda function's input parameters and what your lambda function returns is the output. With AWS Lambda, your output needs to be JSON serializable as well. Here's &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/eventsources.html"&gt;some example events&lt;/a&gt; you might see with AWS Lambda.&lt;/p&gt;

&lt;p&gt;The second argument is the AWS Lambda context, which is a Python object with useful meta data about the lambda function and the current invocation. For example, every invocation has a &lt;code&gt;aws_request_id&lt;/code&gt; which is useful if you want to track down what happened in a specific invocation within your logs. Check &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/python-context-object.html"&gt;here&lt;/a&gt; for more information about the context object. You probably won't need to worry about the context object right away, but you'll eventually find it useful when debugging.&lt;/p&gt;

&lt;p&gt;So how is this useful? Well, if your app/workload can work with a JSON serializable input and produce a JSON serializable output, then it can plug right into a AWS Lambda. If we go back to our two workload categories, web API and worker, we've already pretty much implemented what you'll need for a worker. Lets say we wanted to run our &lt;code&gt;httprequest&lt;/code&gt; function every ten minutes, in order to do that all we would need to do is add the following to our &lt;code&gt;serverless.yml&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;functions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;httprequest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;httprequest.handler&lt;/span&gt;
    &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rate(10 minutes)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And re-deploy:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;sls deploy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And we're done. Now &lt;code&gt;httprequest&lt;/code&gt; is being triggered automatically every ten minutes. If you want more fine-grained control, you can &lt;a href="https://serverless.com/framework/docs/providers/aws/events/schedule/"&gt;specify a specific time&lt;/a&gt; your function should be triggered as well. You can also build more complex workflows using SNS, SQS or other AWS services.&lt;/p&gt;

&lt;p&gt;What about the web API? Remember earlier we covered events and mentioned that an HTTP request can be represented as an event? In the case of web APIs, it is Amazon's API Gateway service that will be triggering the events for us. In addition to this, API Gateway will provide a hostname that can receive HTTP requests, transform those HTTP requests into an event object, invoke our lambda function, collect the response and pass it on to the requester as an HTTP response. That might sound complex, but thankfully the Serverless framework abstracts much of this for us. Let's add an HTTP endpoint to our &lt;code&gt;serverless.yml&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;functions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;webapi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webapi.handler&lt;/span&gt;
    &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
          &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;get&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This looks a lot like our scheduled worker task earlier, doesn't it? Like in the scheduled task, here we configure this handler to handle &lt;code&gt;http&lt;/code&gt; events and specify a &lt;code&gt;path&lt;/code&gt; and &lt;code&gt;method&lt;/code&gt;. As you've likely guessed, the &lt;code&gt;path&lt;/code&gt; is our HTTP request path and the &lt;code&gt;method&lt;/code&gt; is the HTTP method this handler will handle. You'll also notice we've added a new &lt;code&gt;handler&lt;/code&gt;, let's create that now in &lt;code&gt;webapi.py&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"body"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"I'm an HTTP response"&lt;/span&gt;&lt;span class="p"&gt;})}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here our handler will accept an event from the API Gateway and will respond with a JSON serializable dict. Within the dict we have two keys, the first is &lt;code&gt;statusCode&lt;/code&gt; which is the HTTP status code we want the API Gateway to respond with and the second is the HTTP body of the response. You'll also notice that we serialize the &lt;code&gt;body&lt;/code&gt; into JSON as well. The reason we do this is that API Gateway expects the HTTP response body to be a string. So if we want our web API to respond with JSON, we need to serialize it before handing it back to API Gateway. This also means that if you wanted to support some other form of serialization, like XML, YAML or something else -- you could do that, too.&lt;/p&gt;

&lt;p&gt;Now let's deploy it:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;sls deploy
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Once done the Serverless framework will provide us with an endpoint:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;endpoints:
 GET - https://XXXXXXXXXX.execute-api.us-east-1.amazonaws.com/dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Your endpoint will look a little different. What just happened here? Well, in short, Serverless created our new AWS Lambda function and then configured an AWS API Gateway to point to this lambda function. The endpoint you see above is the one provided by API Gateway.&lt;/p&gt;

&lt;p&gt;Let's take our endpoint for a spin:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;curl https://XXXXXXXXXX.execute-api.us-east-1.amazonaws.com/dev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And you should see the following response:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"I'm an HTTP response"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Congratulations, you've just created your first serverless web API. Now you've probably noticed that the URL API Gateway provides is pretty ugly. It would be a lot nicer if it could be something more readable like &lt;code&gt;https://api.mywebapi.com/&lt;/code&gt;. Well, there's a &lt;a href="https://github.com/amplify-education/serverless-domain-manager"&gt;plugin for that&lt;/a&gt;, too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cleaning Up
&lt;/h2&gt;

&lt;p&gt;In this post we've created three Lambda functions and an API Gateway. But these were really just examples to help you get your feet wet in serverless. You'll probably want to clean up and to do that just run:&lt;/p&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;sls remove
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And the Serverless framework will take care of the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Summation
&lt;/h2&gt;

&lt;p&gt;In this post we've gone over some of the AWS Lambda basics and created a simple web API and worker using the Serverless framework. In &lt;a href="https://dev.to/adjohn/the-right-way-to-do-serverless-in-python-part-2-3deg"&gt;Part 2&lt;/a&gt; we cover some more advanced topics, including an introduction to two serverless frameworks specifically built for Python: &lt;a href="https://www.zappa.io"&gt;Zappa&lt;/a&gt; and &lt;a href="https://github.com/aws/chalice"&gt;Chalice&lt;/a&gt;. We also demonstrate how quickly you can build a web API using these tools, including examples using popular web frameworks such as &lt;a href="https://www.djangoproject.com"&gt;Django&lt;/a&gt; and &lt;a href="http://flask.pocoo.org"&gt;Flask&lt;/a&gt;.&lt;/p&gt;


</description>
      <category>serverless</category>
      <category>python</category>
      <category>tutorials</category>
      <category>awslambda</category>
    </item>
  </channel>
</rss>
