DEV Community

Cover image for Azure Functions for Python - Introduction to the new V2 programming model
Manuel Kanetscheider
Manuel Kanetscheider

Posted on

Azure Functions for Python - Introduction to the new V2 programming model

Introduction

Recently, Microsoft introduced a decorator based approach for the development of Python based functions. This concept is very similar to the approach that FastAPI follows. So what has changed?

⚠️ The V2 programming model is currently in public preview. Some things may still change, so the features described here should not be used in production yet. Also, not all trigger types are fully supported at this time.

The V1 programming model

With the v1 programming model, each trigger of a function consists of two files:

  • function.json

    • This is a configuration file that defines, among other things, the trigger type of the function and how the data is bound.
  • __init__.py

    • Contains the actual code of the function and must match the function.json (such as names of input or output variables defined in function.json).

For example, an HTTP Azure Function looks like this:

function.json:

{
    "scriptFile": "__init__.py",
    "bindings": [
        {
            "authLevel": "function",
            "type": "httpTrigger",
            "direction": "in",
            "name": "req",
            "methods": [
                "get",
                "post"
            ]
        },
        {
            "type": "http",
            "direction": "out",
            "name": "$return"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

__init__.py:

import azure.functions


def main(req: azure.functions.HttpRequest) -> str:
    user = req.params.get('user')
    return f'Hello, {user}!'
Enter fullscreen mode Exit fullscreen mode

The V2 programming model

As you could see in the V1 programming model, for each trigger two files are needed, one is a configuration of the trigger and the other is the actual code. This has changed with the V2 programming model, the configuration information can now be placed directly in the code via decoraters.

For example, an HTTP Azure Function looks like this:

import azure.functions

@app.function_name(name="HttpTrigger1")
@app.route(route="req")

def main(req: azure.functions.HttpRequest) -> str:
    user = req.params.get('user')
    return f'Hello, {user}!'
Enter fullscreen mode Exit fullscreen mode

The triggers can now be configured via decorates. The types of the attributes, both input and output, can be specified via type annotations.

At the moment the following triggers and bingings are supported:

Type Trigger Input Output
HTTP
Timer
Azure Queue Storage
Azure Service Bus topic
Azure Servuce Bus queue
Azure Comos DB
Azure Blob Storage
Azure Hub

ℹ️ As you can see here, not all triggers and binding are supported yet, but Microsoft will deliver them later. If your desired type is not listed yet, you have to stay with the programming model V1.
For an up-to-date overview of all supported types, please check out this link.

As you could already see the new programming model V2 leads to a simpler file structure and a more code based approach. Another cool feature introduced are the blueprints.

In case you are familiar with FastAPI, blueprints may remind you of FastAPI router functionality. Blueprint allows to split the Azure Function into several modules and also to create interfaces that can be reused in other projects.

import logging 

import azure.functions as func 

bp = func.Blueprint() 

@bp.route(route="default_template") 
def default_template(req: func.HttpRequest) -> func.HttpResponse: 
    logging.info('Python HTTP trigger function processed a request.') 

    name = req.params.get('name') 
    if not name: 
        try: 
            req_body = req.get_json() 
        except ValueError: 
            pass 
        else: 
            name = req_body.get('name') 

    if name: 
        return func.HttpResponse( 
            f"Hello, {name}. This HTTP-triggered function " 
            f"executed successfully.") 
    else: 
        return func.HttpResponse( 
            "This HTTP-triggered function executed successfully. " 
            "Pass a name in the query string or in the request body for a" 
            " personalized response.", 
            status_code=200 
        )
Enter fullscreen mode Exit fullscreen mode

This blueprint then only needs to be imported and registered:

import azure.functions as func 
from http_blueprint import bp

app = func.FunctionApp() 

app.register_functions(bp)
Enter fullscreen mode Exit fullscreen mode

A unique feature of Azure functions in combination with Python is the use of ASGI and WSGI compatible web frameworks, such as FastAPI or Flask. This is already possible with the programming model V1 and is also maintained here:

ASGI (FastAPI)

# function_app.py

import azure.functions as func 
from fastapi import FastAPI, Request, Response 

fast_app = FastAPI() 

@fast_app.get("/return_http_no_body") 
async def return_http_no_body(): 
    return Response(content='', media_type="text/plain") 

app = func.AsgiFunctionApp(app=fast_app, 
                           http_auth_level=func.AuthLevel.ANONYMOUS)
Enter fullscreen mode Exit fullscreen mode

WSGI (Flask)

# function_app.py

import azure.functions as func 
from flask import Flask, request, Response, redirect, url_for 

flask_app = Flask(__name__) 
logger = logging.getLogger("my-function") 

@flask_app.get("/return_http") 
def return_http(): 
    return Response('<h1>Hello World™</h1>', mimetype='text/html') 

app = func.WsgiFunctionApp(app=flask_app.wsgi_app, 
                           http_auth_level=func.AuthLevel.ANONYMOUS)
Enter fullscreen mode Exit fullscreen mode

Conclusion

These were my highlights of the programming model V2 for Python Azure Fuctions! Although this feature is still in preview, I find these changes incredibly exciting as they allow us to develop Azure Functions with a more code based approach, similar to FastAPI.

However, keep in mind that these are preview features at this time and may change. Also, not all triggers and binding types are
supported currently, but these will surely follow shortly!

Let me know your thoughts on this and thanks for reading!

Resources:

Top comments (0)