functions-framework

FaaS (Function as a service) framework for writing portable Python functions

Showing:

Popularity

Downloads/wk

0

GitHub Stars

381

Maintenance

Last Commit

1mo ago

Contributors

17

Package

Dependencies

5

License

Categories

Readme

Functions Framework for Python Build Status PyPI version

An open source FaaS (Function as a service) framework for writing portable Python functions -- brought to you by the Google Cloud Functions team.

The Functions Framework lets you write lightweight functions that run in many different environments, including:

The framework allows you to go from:

def hello(request):
    return "Hello world!"

To:

curl http://my-url
# Output: Hello world!

All without needing to worry about writing an HTTP server or complicated request handling logic.

Features

  • Spin up a local development server for quick testing
  • Invoke a function in response to a request
  • Automatically unmarshal events conforming to the CloudEvents spec
  • Portable between serverless platforms

Installation

Install the Functions Framework via pip:

pip install functions-framework

Or, for deployment, add the Functions Framework to your requirements.txt file:

functions-framework==2.2.1

Quickstarts

Quickstart: Hello, World on your local machine

Create an main.py file with the following contents:

def hello(request):
    return "Hello world!"

Your function is passed a single parameter, (request), which is a Flask Request object.

Run the following command:

functions-framework --target=hello

Open http://localhost:8080/ in your browser and see Hello world!.

Quickstart: Set up a new project

Create a main.py file with the following contents:

def hello(request):
    return "Hello world!"

Now install the Functions Framework:

pip install functions-framework

Use the functions-framework command to start the built-in local development server:

functions-framework --target hello --debug
 * Serving Flask app "hello" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)

(You can also use functions-framework-python if you potentially have multiple language frameworks installed).

Send requests to this function using curl from another terminal window:

curl localhost:8080
# Output: Hello world!

Quickstart: Error handling

The framework includes an error handler that is similar to the flask.Flask.errorhandler function, which allows you to handle specific error types with a decorator:

import functions_framework


@functions_framework.errorhandler(ZeroDivisionError)
def handle_zero_division(e):
    return "I'm a teapot", 418


def function(request):
    1 / 0
    return "Success", 200

This function will catch the ZeroDivisionError and return a different response instead.

Quickstart: Pub/Sub emulator

  1. Create a main.py file with the following contents:

    def hello(event, context):
         print("Received", context.event_id)
    
  2. Start the Functions Framework on port 8080:

    functions-framework --target=hello --signature-type=event --debug --port=8080
    
  3. In a second terminal, start the Pub/Sub emulator on port 8085.

    export PUBSUB_PROJECT_ID=my-project
    gcloud beta emulators pubsub start \
        --project=$PUBSUB_PROJECT_ID \
        --host-port=localhost:8085
    

    You should see the following after the Pub/Sub emulator has started successfully:

    [pubsub] INFO: Server started, listening on 8085
    
  4. In a third terminal, create a Pub/Sub topic and attach a push subscription to the topic, using http://localhost:8080 as its push endpoint. Publish some messages to the topic. Observe your function getting triggered by the Pub/Sub messages.

    export PUBSUB_PROJECT_ID=my-project
    export TOPIC_ID=my-topic
    export PUSH_SUBSCRIPTION_ID=my-subscription
    $(gcloud beta emulators pubsub env-init)
    
    git clone https://github.com/googleapis/python-pubsub.git
    cd python-pubsub/samples/snippets/
    pip install -r requirements.txt
    
    python publisher.py $PUBSUB_PROJECT_ID create $TOPIC_ID
    python subscriber.py $PUBSUB_PROJECT_ID create-push $TOPIC_ID $PUSH_SUBSCRIPTION_ID http://localhost:8080
    python publisher.py $PUBSUB_PROJECT_ID publish $TOPIC_ID
    

    You should see the following after the commands have run successfully:

    Created topic: projects/my-project/topics/my-topic
    
    topic: "projects/my-project/topics/my-topic"
    push_config {
      push_endpoint: "http://localhost:8080"
    }
    ack_deadline_seconds: 10
    message_retention_duration {
      seconds: 604800
    }
    .
    Endpoint for subscription is: http://localhost:8080
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Published messages to projects/my-project/topics/my-topic.
    

    And in the terminal where the Functions Framework is running:

     * Serving Flask app "hello" (lazy loading)
     * Environment: production
       WARNING: This is a development server. Do not use it in a production deployment.
       Use a production WSGI server instead.
     * Debug mode: on
     * Running on http://0.0.0.0:8080/ (Press CTRL+C to quit)
     * Restarting with fsevents reloader
     * Debugger is active!
     * Debugger PIN: 911-794-046
    Received 1
    127.0.0.1 - - [11/Aug/2021 14:42:22] "POST / HTTP/1.1" 200 -
    Received 2
    127.0.0.1 - - [11/Aug/2021 14:42:22] "POST / HTTP/1.1" 200 -
    Received 5
    127.0.0.1 - - [11/Aug/2021 14:42:22] "POST / HTTP/1.1" 200 -
    Received 6
    127.0.0.1 - - [11/Aug/2021 14:42:22] "POST / HTTP/1.1" 200 -
    Received 7
    127.0.0.1 - - [11/Aug/2021 14:42:22] "POST / HTTP/1.1" 200 -
    Received 8
    127.0.0.1 - - [11/Aug/2021 14:42:22] "POST / HTTP/1.1" 200 -
    Received 9
    127.0.0.1 - - [11/Aug/2021 14:42:39] "POST / HTTP/1.1" 200 -
    Received 3
    127.0.0.1 - - [11/Aug/2021 14:42:39] "POST / HTTP/1.1" 200 -
    Received 4
    127.0.0.1 - - [11/Aug/2021 14:42:39] "POST / HTTP/1.1" 200 -
    

For more details on extracting data from a Pub/Sub event, see https://cloud.google.com/functions/docs/tutorials/pubsub#functions_helloworld_pubsub_tutorial-python

Quickstart: Build a Deployable Container

  1. Install Docker and the pack tool.

  2. Build a container from your function using the Functions buildpacks:

    pack build \
        --builder gcr.io/buildpacks/builder:v1 \
        --env GOOGLE_FUNCTION_SIGNATURE_TYPE=http \
        --env GOOGLE_FUNCTION_TARGET=hello \
        my-first-function
    
  3. Start the built container:

    docker run --rm -p 8080:8080 my-first-function
    # Output: Serving function...
    
  4. Send requests to this function using curl from another terminal window:

    curl localhost:8080
    # Output: Hello World!
    

Run your function on serverless platforms

Google Cloud Functions

This Functions Framework is based on the Python Runtime on Google Cloud Functions.

On Cloud Functions, using the Functions Framework is not necessary: you don't need to add it to your requirements.txt file.

After you've written your function, you can simply deploy it from your local machine using the gcloud command-line tool. Check out the Cloud Functions quickstart.

Cloud Run/Cloud Run on GKE

Once you've written your function and added the Functions Framework to your requirements.txt file, all that's left is to create a container image. Check out the Cloud Run quickstart for Python to create a container image and deploy it to Cloud Run. You'll write a Dockerfile when you build your container. This Dockerfile allows you to specify exactly what goes into your container (including custom binaries, a specific operating system, and more). Here is an example Dockerfile that calls Functions Framework.

If you want even more control over the environment, you can deploy your container image to Cloud Run on GKE. With Cloud Run on GKE, you can run your function on a GKE cluster, which gives you additional control over the environment (including use of GPU-based instances, longer timeouts and more).

Container environments based on Knative

Cloud Run and Cloud Run on GKE both implement the Knative Serving API. The Functions Framework is designed to be compatible with Knative environments. Just build and deploy your container to a Knative environment.

Configure the Functions Framework

You can configure the Functions Framework using command-line flags or environment variables. If you specify both, the environment variable will be ignored.

Command-line flagEnvironment variableDescription
--hostHOSTThe host on which the Functions Framework listens for requests. Default: 0.0.0.0
--portPORTThe port on which the Functions Framework listens for requests. Default: 8080
--targetFUNCTION_TARGETThe name of the exported function to be invoked in response to requests. Default: function
--signature-typeFUNCTION_SIGNATURE_TYPEThe signature used when writing your function. Controls unmarshalling rules and determines which arguments are used to invoke your function. Default: http; accepted values: http, event or cloudevent
--sourceFUNCTION_SOURCEThe path to the file containing your function. Default: main.py (in the current working directory)
--debugDEBUGA flag that allows to run functions-framework to run in debug mode, including live reloading. Default: False
--dry-runDRY_RUNA flag that allows for testing the function build from the configuration without creating a server. Default: False

Enable Google Cloud Functions Events

The Functions Framework can unmarshall incoming Google Cloud Functions event payloads to event and context objects. These will be passed as arguments to your function when it receives a request. Note that your function must use the event-style function signature:

def hello(event, context):
    print(event)
    print(context)

To enable automatic unmarshalling, set the function signature type to event using the --signature-type command-line flag or the FUNCTION_SIGNATURE_TYPE environment variable. By default, the HTTP signature will be used and automatic event unmarshalling will be disabled.

For more details on this signature type, see the Google Cloud Functions documentation on background functions.

See the running example.

Enable CloudEvents

The Functions framework can also unmarshall incoming CloudEvents payloads to the cloudevent object. This will be passed as a cloudevent to your function when it receives a request. Note that your function must use the cloudevents-style function signature:

def hello(cloudevent):
    print(f"Received event with ID: {cloudevent['id']}")

To enable automatic unmarshalling, set the function signature type to cloudevent using the --signature-type command-line flag or the FUNCTION_SIGNATURE_TYPE environment variable. By default, the HTTP signature type will be used and automatic event unmarshalling will be disabled.

For more details on this signature type, check out the Google Cloud Functions documentation on background functions.

Advanced Examples

More advanced guides can be found in the examples/ directory. You can also find examples on using the CloudEvent Python SDK here.

Contributing

Contributions to this library are welcome and encouraged. See CONTRIBUTING for more information on how to get started.

Rate & Review

Great Documentation0
Easy to Use0
Performant0
Highly Customizable0
Bleeding Edge0
Responsive Maintainers0
Poor Documentation0
Hard to Use0
Slow0
Buggy0
Abandoned0
Unwelcoming Community0
100