Create Google Cloud Functions Running Python 3.7

GCP scores another victory by trivializing serverless functions

The more I explore Google Cloud's endless catalog of cloud services, the more I really like Google Cloud. This is why before moving forward, I'd like to be transparent that this blog has become little more than thinly veiled Google propaganda, where I will henceforth bombard you with persuasive and subtle messaging to sell your soul to Google. Let's be honest; they've probably simulated it anyway.

It should be safe to assume that you're fairly familiar with AWS Lambda Functions, which have served as the backbone of what we refer to as "serverless." These code snippets in the cloud have restructured entire IT departments and are partially why almost nobody knows enough basic Linux to configure a web server or build anything without a vendor. In my opinion, Google Cloud Functions are better than that, so strap in.

AWS vs GCP Workflow Comparison

AWS' architecture philosophy leans heavily towards chaining together services into what inevitably becomes a web of self-contained billable items on your invoice. A fine illustration of this is a fine post on common AWS patterns, which provides a decent visual of this complexity, while also revealing how much people apparently love this kind of shit, as though SaaS is the new Legos.

To interact with a Lambda function in AWS via HTTP requests, AWS, you need to set up an API Gateway in front. This is a feat sometimes as daunting as coding itself, followed by a user permission struggle just to get your your user the access to create Lambdas, as well as individual policies associated with *every other microservice you hope to interact with.*  

Eventually, you’ll get to write some code or upload a horrendous zip file like some sort of neanderthal (friendly reminder: I am entirely biased and actively attempting to brainwash you.)

GCP has clearly been taking notes on the sidelines on how to improve this process by removing red tape around service setup or policy configuration. AWS and GCP are tackling opposites approaches; AWS allows you to build a Robust API complete with staging and testing with the intent that some of these APIs can even be sold as standalone products to consumers. GCP takes the opposite approach: cloud functions are services intended for developers to develop, which covers the vast majority of use cases in my opinion.

Cloud Function Deployment

To create our first function to serve as an endpoint, we'll utilize the following:

  • A new Cloud Function running Python 3.7
  • Google's Source Repositories: AKA a Github/Bitbucket clone with auto-syncing to your real repos, along with direct access to GCP services (think Heroku's source control).
  • The gcloud CLI to enable us to work locally.

You should immediately notice the glaring lack of any mentions of API endpoints, methods, stages, or anything related to handling web requests. It should not be understated that Cloud Functions are preconfigured with an endpoint, and all nonsense regarding whether endpoints accept GET or POST or AUTH or OPTIONs is missing entirely. These things are handled in the function itself, and because Google Cloud functions running Python are preconfigured with Flask, all of that stuff is really trivially easy. That's right, we've got Flask, Python, and GCP all in a single post. Typing these words feels like eating cake while Dwyane The Rock Johnson reads me bedtime stories and caresses me as I fall asleep. It's great.

Create your Function

Our function will intend to serve as a Python HTTP endpoint:

Single-page setup. Easy.
  • Trigger specifies what will have access to this function. By selecting HTTP, we will immediately receive a URL.
  • Source code gives us a few options to deploy our code with cloud source repository being by far the easiest solution, especially when working locally.
  • Runtime allows you to select NodeJS by accident.

Before we get to code, let's talk Python libraries.

Including Dependencies in your Function

Our function comes prepared with two files: and our friend requirements.txt. These files do exactly what you'd expect, as per every project ever:

Unfortunately, ease-of-use ensures that GCP certifications will be in low demand.

Our function immediately installs all dependencies in requirements.txt for use upon deployment. Once deployed, we can import these libraries as expected. So, let's deploy something.

Google Source Repositories

Google's source repositories can serve as a stand-in replacement for Github (unlikely), or auto-sync to any repo on the version control behememoth of your choice. The advantage of this extra layer is mostly to trigger deployments upon commits, which in turn feed into GCP's own CI/CD processes (which remain young for now). Create a repo locally using gcloud:

$ gcloud source repos create real-repo
$ cd myproject/
$ git init
(take a moment to write or save some actual code here)
$ git add --all
$ git remote add google
$ git commit -m 'cheesey init message'
$ git push --all google

Now make that puppy go live with gcloud functions deploy totally-dope-function, where totally-dope-function is name of your function, as it should be.

Now let's get to the coding part.

The Coding Part (ft. Flask)

Here's perhaps the most basic endpoint you'll ever create:

import requests

def endpoint(request):
    """Does the things."""
    if request.method == 'POST':
    # Allows POST requests from any origin with the Content-Type
    # header and caches preflight response for an 3600s
    headers = {
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'POST',
        'Access-Control-Allow-Headers': 'Content-Type',
        'Access-Control-Max-Age': '3600'
    request_json = request.get_json()
    if request_json:
        plaintext = request_json['plain']
        html = request_json['html']
        return html
        return 'You didn't pass a JSON body you idiot.'

If you're familiar with Flask (you are, because you're on this blog) you already know what all of this does. Look at that simple copy-paste of headers, as opposed to working them into a horrible web interface. Gasp in disbelief as you realize that typing if request.method == 'POST': would be a 10-minute task in a visual API building tool. We've made it fam.

Ease of Logging

Because we have a real endpoint to work with, we don't need to waste any time simulating stupid fucking tests where we send fake JSON to our function. We can use postman or anything to immediately interact with our endpoint, and the logs are a click away:

Easy. Breezy. Beautiful.

There's no point in me droning on at this point because you've surely already ventured into the Google Cloud console in blissful disbelief as a good obedient drone would. If adopting Google Cloud is the last shred of hope we have to resist Google's all-knowing algorithms which have already replaced the illusion of free will, I'd gladly take that dystopia over setting up monolithic API Gateways any day.

The Downsides

Time for the asterisks* to kill that euphoric buzz you might've experienced for a brief moment. My sole purpose as an engineer is to have my dreams crushed full-time; I simply cant resist returning the favor.

First notable drawback of Cloud functions is a lack of out-of-the-box custom DNS configuration. Firebase has workarounds for this, but Firebase is a beast of its own.

When it comes to debugging, functions tend to fall short in comparison to their Lambda rivals. Other than deploying, testing, and softing through cryptic error logs (they can be quite bad), there's no UI mock testing to speak up. You'd better brush up on PyTest.

Finally, if I'm not mistaken, Google Cloud functions charge based on their existence, as opposed to usage. If you get used to Google Cloud, be ready to receive bills for 200-300 dollars for a bunch of services you thought were idle. I can barely express how curiosity has left me financially fucked. Doesn't seem like the type of values a company which toots it's own innovation horn would hold, does it now?

Todd Birchard Author image
New York City Website
Product manager turned engineer with an ongoing identity crisis. Breaks everything before learning best practices. Completely normal and emotionally stable.

Product manager turned engineer with an ongoing identity crisis. Breaks everything before learning best practices. Completely normal and emotionally stable.