Using the Python functions-framework for serverless development

Torben Dury · October 19, 2022

The functions-framework is a serverless framework published and maintained by the Google Cloud Functions team. It is free and publicly available for everyone on GitHub.

Use Cases

You can use it for rapid development of lightweight and portable Python functions that (do not only) run on Google Cloud Function environments. It also runs on any Knative-based environments as well as Cloud Run and of course Cloud Run for GKE/Anthos. The best of it? It also runs on your local machine like it would run on the public cloud, including HTTP traffic as well as event-driven functions.

Quickstart

For local development, it is recommended that you install the functions-framework package with pip:

pip install functions-framework

Or add the following to your requirements.txt:

functions-framework==3.*

Note: For Google Cloud Functions, you do not need to specify the above line in your requirements.txt.

HTTP Example

Let’s start with a simple HTTP example. Serverless functions typically have an entrypoint that is defined when deploying the function. Note that there are patterns where your entrypoint is only a relay function that parses requests to other nested functions.

The Hello World of the functions-framework is as easy as:

import functions_framework

@functions_framework.http
def entrypoint(request):
    return "Hello world!"

Save this code snippet as main.py, spin up a terminal and type:

functions-framework --target entrypoint --debug

And start making requests:

curl localhost:8080/

You can also define different routes for your functions or handle request headers and body handed over as a request object.

(Cloud) Event Example

A big plus for the functions-framework is that it provides a decorator for reacting to events. Event-driven architectures are being advertised and developed and find a wider audience than they used to, so with the functions-framework you are perfectly prepared for implementing event-driven approaches.

The functions-framework also implements the CloudEvents specification which also is a big plus.

To consume an event, take this quickstart example:

import functions_framework

@functions_framework.cloud_event
def entrypoint(cloud_event):
   print(f"Received event with id {cloud_event['id']} and data {cloud_event.data}")

Run your application with functions-framework –target=entrypoint and push an event:

curl -X POST localhost:8080 \
   -H "Content-Type: application/cloudevents+json" \
   -d '{
    "specversion" : "1.0",
    "type" : "torben.techblog.cloud.event",
    "source" : "https://torbentechblog.com/cloudevents/pull",
    "subject" : "sensor_event",
    "id" : "A234-1234-1234",
    "time" : "2022-10-19T13:37:00Z",
    "data" : "31.2"
}'

Your function then should log the following line: Received event with id A234-1234-1234 and data 31.2

Emulating event platforms

Using curl for very small tests while developing your function might be suitable for you, but most of the time you will want a full emulation of the cloud platform your code will be deployed to.

Let’s assume that you want to deploy your function to Google Cloud Functions and it should listen to Google Pub/Sub events. Pub/Sub does not enforce CloudEvents specifications, so neither will we.

Write a function like this:

def entrypoint(event, context):
     print(f"Received {context.event_id}")

And start it locally like the other functions.

In a second terminal, you can use the gcloud CLI to start a local Pub/Sub emulator (Note that it does not fully implement everything you get with Pub/Sub):

export PUBSUB_PROJECT_ID=torbentechblog
# 8080 is already taken by functions-framework
gcloud beta emulators pubsub start \
    --project=$PUBSUB_PROJECT_ID \
    --host-port=localhost:8085

And begin sending messages to the emulated Pub/Sub instance. If you need help with pushing messages, have a look at the official documentation that has a very good quickstart prepared for you.

Conclusion

The functions-framework by Google Cloud Functions team is still pretty young in the framework world, so there might be big changes in the future that you will or will not like. The team itself says that they do not want to be another abstraction layer for Flask applications (although the framework relies on Flask under the hood), so the framework does not implement the full feature set of Flask and the team is not planning to do so.

Still, the functions-framework is a very interesting framework that can really enhance your development speed when it comes to serverless functions. The way it provides you a stable base for starting your development really leaves the standard hassle behind.

In near future, I will also write a post for testing and implementing error handling on your functions-framework code, so stay tuned for more!

XING, LinkedIn, Twitter, Facebook