Quickstart: Create a Python Durable Functions app

Use Durable Functions, a feature of Azure Functions, to write stateful functions in a serverless environment. You install Durable Functions by installing the Azure Functions extension in Visual Studio Code. The extension manages state, checkpoints, and restarts in your application.

In this quickstart, you use the Durable Functions extension in Visual Studio Code to locally create and test a "hello world" Durable Functions app in Azure Functions. The Durable Functions app orchestrates and chains together calls to other functions. Then, you publish the function code to Azure. The tools you use are available via the Visual Studio Code extension.

Screenshot of the running Durable Functions app in Azure.

Prerequisites

To complete this quickstart, you need:

If you don't have an Azure subscription, create a trial account before you begin.

Create your local project

In this section, you use Visual Studio Code to create a local Azure Functions project.

  1. In Visual Studio Code, select F1 (or select Ctrl/Cmd+Shift+P) to open the command palette. At the prompt (>), enter and then select Azure Functions: Create New Project.

    Screenshot of Create function window.

  2. Select Browse. In the Select Folder dialog, go to a folder to use for your project, and then choose Select.

  1. At the prompts, provide the following information:

    Prompt Action Description
    Select a language for your function app project Select Python. Creates a local Python Functions project.
    Select a version Select Azure Functions v4. You see this option only when Core Tools isn't already installed. In this case, Core Tools is installed the first time you run the app.
    Python version Select Python 3.7, Python 3.8, Python 3.9, or Python 3.10. Visual Studio Code creates a virtual environment by using the version you select.
    Select a template for your project's first function Select Skip for now.
    Select how you would like to open your project Select Open in current window. Opens Visual Studio Code in the folder you selected.
  1. At the prompts, provide the following information:

    Prompt Value Description
    Select a language Select Python (Programming Model V2). Creates a local Python Functions project by using the V2 programming model.
    Select a version Select Azure Functions v4. You see this option only when Core Tools isn't already installed. In this case, Core Tools is installed the first time you run the app.
    Python version Select Python 3.7, Python 3.8, Python 3.9, or Python 3.10. Visual Studio Code creates a virtual environment by using the version you select.
    Select how you would like to open your project Select Open in current window. Opens Visual Studio Code in the folder you selected.

Visual Studio Code installs Azure Functions Core Tools if it's required to create a project. It also creates a function app project in a folder. This project contains the host.json and local.settings.json configuration files.

A requirements.txt file is also created in the root folder. It specifies the Python packages required to run your function app.

Install azure-functions-durable from PyPI

When you create the project, the Azure Functions Visual Studio Code extension automatically creates a virtual environment with your selected Python version. You then need to activate the virtual environment in a terminal and install some dependencies required by Azure Functions and Durable Functions.

  1. Open the requirements.txt in the editor and change its content to the following code:

    azure-functions
    azure-functions-durable
    
  2. In the current folder, open the editor's integrated terminal (Ctrl+Shift+`).

  3. In the integrated terminal, activate the virtual environment in the current folder, depending on your operating system.

    source .venv/bin/activate
    

Then, in the integrated terminal where the virtual environment is activated, use pip to install the packages you defined.

python -m pip install -r requirements.txt

Create your functions

The most basic Durable Functions app has three functions:

  • Orchestrator function: A workflow that orchestrates other functions.
  • Activity function: A function that is called by the orchestrator function, performs work, and optionally returns a value.
  • Client function: A regular function in Azure that starts an orchestrator function. This example uses an HTTP-triggered function.

Orchestrator function

You use a template to create the Durable Functions app code in your project.

  1. In the command palette, enter and then select Azure Functions: Create Function.

  2. At the prompts, provide the following information:

    Prompt Action Description
    Select a template for your function Select Durable Functions orchestrator. Creates a Durable Functions app orchestration.
    Provide a function name Select HelloOrchestrator. A name for your durable function.

You added an orchestrator to coordinate activity functions. Open HelloOrchestrator/__init__.py to see the orchestrator function. Each call to context.call_activity invokes an activity function named Hello.

Next, you add the referenced Hello activity function.

Activity function

  1. In the command palette, enter and then select Azure Functions: Create Function.

  2. At the prompts, provide the following information:

    Prompt Action Description
    Select a template for your function Select Durable Functions activity. Creates an activity function.
    Provide a function name Enter Hello. The name of your activity function.

You added the Hello activity function that is invoked by the orchestrator. Open Hello/__init__.py to see that it takes a name as input and returns a greeting. An activity function is where you perform actions such as making a database call or performing a computation.

Finally, you add an HTTP-triggered function that starts the orchestration.

Client function (HTTP starter)

  1. In the command palette, enter and then select Azure Functions: Create Function.

  2. At the prompts, provide the following information:

    Prompt Action Description
    Select a template for your function Select Durable Functions HTTP starter. Creates an HTTP starter function.
    Provide a function name Enter DurableFunctionsHttpStart. The name of your client function
    Authorization level Select Anonymous. For demo purposes, this value allows the function to be called without using authentication.

You added an HTTP-triggered function that starts an orchestration. Open DurableFunctionsHttpStart/__init__.py to see that it uses client.start_new to start a new orchestration. Then it uses client.create_check_status_response to return an HTTP response containing URLs that can be used to monitor and manage the new orchestration.

You now have a Durable Functions app that can be run locally and deployed to Azure.

Requirements

Version 2 of the Python programming model requires the following minimum versions:

Enable the v2 programming model

The following application setting is required to run the v2 programming model:

  • Name: AzureWebJobsFeatureFlags
  • Value: EnableWorkerIndexing

If you're running locally by using Azure Functions Core Tools, add this setting to your local.settings.json file. If you're running in Azure, complete these steps by using a relevant tool:

Replace <FUNCTION_APP_NAME> and <RESOURCE_GROUP_NAME> with the name of your function app and resource group, respectively.

az functionapp config appsettings set --name <FUNCTION_APP_NAME> --resource-group <RESOURCE_GROUP_NAME> --settings AzureWebJobsFeatureFlags=EnableWorkerIndexing

To create a basic Durable Functions app by using these three function types, replace the contents of function_app.py with the following Python code:

import azure.functions as func
import azure.durable_functions as df

myApp = df.DFApp(http_auth_level=func.AuthLevel.ANONYMOUS)

# An HTTP-triggered function with a Durable Functions client binding
@myApp.route(route="orchestrators/{functionName}")
@myApp.durable_client_input(client_name="client")
async def http_start(req: func.HttpRequest, client):
    function_name = req.route_params.get('functionName')
    instance_id = await client.start_new(function_name)
    response = client.create_check_status_response(req, instance_id)
    return response

# Orchestrator
@myApp.orchestration_trigger(context_name="context")
def hello_orchestrator(context):
    result1 = yield context.call_activity("hello", "Seattle")
    result2 = yield context.call_activity("hello", "Tokyo")
    result3 = yield context.call_activity("hello", "London")

    return [result1, result2, result3]

# Activity
@myApp.activity_trigger(input_name="city")
def hello(city: str):
    return f"Hello {city}"

Review the following table for an explanation of each function and its purpose in the sample:

Method Description
hello_orchestrator The orchestrator function, which describes the workflow. In this case, the orchestration starts, invokes three functions in a sequence, and then returns the ordered results of all three functions in a list.
hello The activity function, which performs the work that is orchestrated. The function returns a simple greeting to the city passed as an argument.
http_start An HTTP-triggered function that starts an instance of the orchestration and returns a check status response.

Note

Durable Functions also supports Python v2 blueprints. To use blueprints, register your blueprint functions by using the azure-functions-durable Blueprint class. You can register the resulting blueprint as usual. You can use our sample as an example.

Test the function locally

Azure Functions Core Tools gives you the capability to run an Azure Functions project on your local development computer. If it isn't installed, you're prompted to install these tools the first time you start a function in Visual Studio Code.

  1. To test your function, set a breakpoint in the Hello activity function code (in Hello/__init__.py). Select F5 or select Debug: Start Debugging in the command palette to start the function app project. Output from Core Tools appears in the terminal panel.

    Note

    For more information about debugging, see Durable Functions diagnostics.

  1. To test your function, set a breakpoint in the hello activity function code. Select F5 or select Debug: Start Debugging in the command palette to start the function app project. Output from Core Tools appears in the terminal panel.

    Note

    For more information about debugging, see Durable Functions diagnostics.

  1. Durable Functions requires an Azure storage account to run. When Visual Studio Code prompts you to select a storage account, select Select storage account.

    Screenshot of how to create a storage account.

  2. At the prompts, provide the following information to create a new storage account in Azure.

    Prompt Action Description
    Select subscription Select the name of your subscription. Your Azure subscription.
    Select a storage account Select Create a new storage account.
    Enter the name of the new storage account Enter a unique name. The name of the storage account to create.
    Select a resource group Enter a unique name. The name of the resource group to create.
    Select a location Select an Azure region. Select a region that is close to you.
  3. In the terminal panel, copy the URL endpoint of your HTTP-triggered function.

    Screenshot of Azure local output.

  1. Use your browser or an HTTP test tool to send an HTTP POST request to the URL endpoint.

    Replace the last segment with the name of the orchestrator function (HelloOrchestrator). The URL should be similar to http://localhost:7071/api/orchestrators/HelloOrchestrator.

    The response is the HTTP function's initial result. It lets you know that the durable orchestration has started successfully. It doesn't yet display the end result of the orchestration. The response includes a few useful URLs. For now, query the status of the orchestration.

  2. Copy the URL value for statusQueryGetUri, paste it in your browser's address bar, and execute the request. You can also continue to use your HTTP test tool to issue the GET request.

    The request queries the orchestration instance for the status. You should see that the instance finished and that it includes the outputs or results of the durable function. It looks similar to this example:

    {
        "name": "HelloOrchestrator",
        "instanceId": "9a528a9e926f4b46b7d3deaa134b7e8a",
        "runtimeStatus": "Completed",
        "input": null,
        "customStatus": null,
        "output": [
            "Hello Tokyo!",
            "Hello Seattle!",
            "Hello London!"
        ],
        "createdTime": "2020-03-18T21:54:49Z",
        "lastUpdatedTime": "2020-03-18T21:54:54Z"
    }
    
  1. Use your browser or an HTTP test tool to send an HTTP POST request to the URL endpoint.

    Replace the last segment with the name of the orchestrator function (HelloOrchestrator). The URL should be similar to http://localhost:7071/api/orchestrators/HelloOrchestrator.

    The response is the HTTP function's initial result. It lets you know that the durable orchestration has started successfully. It doesn't yet display the end result of the orchestration. The response includes a few useful URLs. For now, query the status of the orchestration.

  2. Copy the URL value for statusQueryGetUri, paste it in your browser's address bar, and execute the request. You can also continue to use your HTTP test tool to issue the GET request.

    The request queries the orchestration instance for the status. You should see that the instance finished and that it includes the outputs or results of the durable function. It looks similar to this example:

    {
        "name": "hello_orchestrator",
        "instanceId": "9a528a9e926f4b46b7d3deaa134b7e8a",
        "runtimeStatus": "Completed",
        "input": null,
        "customStatus": null,
        "output": [
            "Hello Tokyo!",
            "Hello Seattle!",
            "Hello London!"
        ],
        "createdTime": "2020-03-18T21:54:49Z",
        "lastUpdatedTime": "2020-03-18T21:54:54Z"
    }
    
  1. To stop debugging, in Visual Studio Code, select Shift+F5.

After you verify that the function runs correctly on your local computer, it's time to publish the project to Azure.

Sign in to Azure

Before you can publish your app, you must sign in to Azure.

  1. If you aren't already signed in, choose the Azure icon in the Activity bar. Then in the Resources area, choose Sign in to Azure....

    Screenshot of the sign-in to Azure window within VS Code.

    If you're already signed in and can see your existing subscriptions, go to the next section. If you don't yet have an Azure account, choose Create an Azure Account.... Students can choose Create an Azure for Students Account....

  2. When prompted in the browser, choose your Azure account and sign in using your Azure account credentials. If you create a new account, you can sign in after your account is created.

  3. After you've successfully signed in, you can close the new browser window. The subscriptions that belong to your Azure account are displayed in the sidebar.

Create the function app in Azure

In this section, you create a function app and related resources in your Azure subscription.

  1. Choose the Azure icon in the Activity bar. Then in the Resources area, select the + icon and choose the Create Function App in Azure option.

    Create a resource in your Azure subscription

  2. Provide the following information at the prompts:

    Prompt Selection
    Select subscription Choose the subscription to use. You won't see this prompt when you have only one subscription visible under Resources.
    Enter a globally unique name for the function app Type a name that is valid in a URL path. The name you type is validated to make sure that it's unique in Azure Functions.
    Select a runtime stack Choose the language version on which you've been running locally.
    Select a location for new resources For better performance, choose a region near you.

    The extension shows the status of individual resources as they're being created in Azure in the Azure: Activity Log panel.

    Log of Azure resource creation

  3. When the creation is complete, the following Azure resources are created in your subscription. The resources are named based on your function app name:

    • A resource group, which is a logical container for related resources.
    • A standard Azure Storage account, which maintains state and other information about your projects.
    • A function app, which provides the environment for executing your function code. A function app lets you group functions as a logical unit for easier management, deployment, and sharing of resources within the same hosting plan.
    • An App Service plan, which defines the underlying host for your function app.
    • An Application Insights instance connected to the function app, which tracks usage of your functions in the app.

    A notification is displayed after your function app is created and the deployment package is applied.

    Tip

    By default, the Azure resources required by your function app are created based on the function app name you provide. By default, they're also created in the same new resource group with the function app. If you want to either customize the names of these resources or reuse existing resources, you need to publish the project with advanced create options instead.

Deploy the project to Azure

Important

Deploying to an existing function app always overwrites the contents of that app in Azure.

  1. Choose the Azure icon in the Activity bar, then in the Workspace area, select your project folder and select the Deploy... button.

    Deploy project from the Visual Studio Code workspace

  2. Select Deploy to Function App..., choose the function app you just created, and select Deploy.

  3. After deployment completes, select View Output to view the creation and deployment results, including the Azure resources that you created. If you miss the notification, select the bell icon in the lower right corner to see it again.

    Screenshot of the View Output window.

Test your function in Azure

  1. Copy the URL of the HTTP trigger from the output panel. The URL that calls your HTTP-triggered function must be in this format:

    https://<functionappname>.chinacloudsites.cn/api/orchestrators/HelloOrchestrator

  1. Copy the URL of the HTTP trigger from the output panel. The URL that calls your HTTP-triggered function must be in this format:

    https://<functionappname>.chinacloudsites.cn/api/orchestrators/hello_orchestrator

  1. Paste the new URL for the HTTP request in your browser's address bar. When you use the published app, you can expect to get the same status response that you got when you tested locally.

The Python Durable Functions app that you created and published by using Visual Studio Code is ready to use.

Clean up resources

If you no longer need the resources that you created to complete the quickstart, to avoid related costs in your Azure subscription, delete the resource group and all related resources.