Creating Azure Function App for Python with Azure Functions Core Tools CLI

We cannot specify the Python runtime version with FUNCTIONS_EXTENSION_VERSION. The FUNCTIONS_EXTENSION_VERSION setting is specifically for specifying the version of the Azure Functions runtime, not the version of Python.

The Azure Functions runtime is the host that runs your functions. It's a separate concept from the Python runtime. Each version of the Azure Functions runtime has a range of versions of Python (and other languages) that it supports, but you can't use the FUNCTIONS_EXTENSION_VERSION setting to choose a specific Python version.

The version of Python that's used in your function app is typically determined by the environment in which the app is running. When running locally, this will be the version of Python that's available in your local environment. When running in Azure, the Python version is determined by the configuration of your Azure Functions host.

If you want to specify a Python version for local development, you can do so using a Python version management tool like pyenv, and creating a .python-version file in the root of your function app project. For deployment in Azure, you specify the Python version when you create the Function App.

Remember to check the Azure Functions runtime support for your chosen Python version. Azure Functions 4.x runtime supports Python 3.7, 3.8, 3.9 and 3.10 for now.

Prerequisite check for Python

$ az --version
$ az login
$ func --version
$ python --version

Create and activate a virtual environment with virtualenv package manager

virtualenv (for Python 2) and venv (for Python 3) allow you to manage separate package installations for different projects.

$ mkdir azure-demo
$ cd azure-demo
$ pyenv local 3.10.5
$ python -m venv .venv
azure-demo/
└── .venv
    ├── bin
    │   ├── Activate.ps1
    │   ├── activate
    │   ├── activate.csh
    │   ├── activate.fish
    │   ├── pip
    │   ├── pip3
    │   ├── pip3.10
    │   ├── python -> /Users/kenanhancer/.pyenv/versions/3.10.5/bin/python
    │   ├── python3 -> python
    │   └── python3.10 -> python
    ├── include
    ├── lib
    │   └── python3.10
    └── pyvenv.cfg
$ source .venv/bin/activate

Running above command in terminal will chage it as below, as seen pip list just shows two python packages.

Create a local function project

The v2 programming model provides a decorator based approach to create functions. To learn more about the Python v2 programming model, see the Developer Reference Guide.

$ func init --python -m V2
import azure.functions as func
import logging

app = func.FunctionApp()
{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "AzureWebJobsFeatureFlags": "EnableWorkerIndexing",
    "AzureWebJobsStorage": "UseDevelopmentStorage=true"
  }
}

If there are more than one Azure Function app, then we can change default host port with LocalHttpPort as below;

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "AzureWebJobsFeatureFlags": "EnableWorkerIndexing",
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "FUNCTIONS_EXTENSION_VERSION": "~4"
  },
  "Host": {
    "LocalHttpPort": 7072
  }
}
{
  "version": "2.0",
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.*, 5.0.0)"
  }
}
azure-demo/
├── .funcignore
├── .gitignore
├── .venv
│   ├── bin
│   │   ├── Activate.ps1
│   │   ├── activate
│   │   ├── activate.csh
│   │   ├── activate.fish
│   │   ├── pip
│   │   ├── pip3
│   │   ├── pip3.10
│   │   ├── python -> /Users/kenanhancer/.pyenv/versions/3.10.5/bin/python
│   │   ├── python3 -> python
│   │   └── python3.10 -> python
│   ├── include
│   ├── lib
│   │   └── python3.10
│   │       └── site-packages
│   └── pyvenv.cfg
├── function_app.py
├── host.json
├── local.settings.json
└── requirements.txt

Create a HTTP trigger function

$ func new --name HttpExample --template "HTTP trigger" --authlevel "anonymous"

HttpExample function is added after line number 4 in function_app.py as below;

To get the invocation context of a function when it's running, include the context argument in its signature as below;

Test a HTTP trigger function

$ curl http://localhost:7071/api/HttpExample?name=Azure
$ curl -X POST -H "Content-Type: application/json" -d '{ "name": "Azure" }' http://localhost:7071/api/HttpExample