Ontwikkelaarshandleiding voor Azure Functions Python

Deze handleiding is een inleiding tot het ontwikkelen van Azure Functions met behulp van Python. In het artikel wordt ervan uitgegaan dat u de ontwikkelaarshandleiding van Azure Functions al hebt gelezen.

Belangrijk

Dit artikel ondersteunt zowel het v1- als v2-programmeermodel voor Python in Azure Functions. Het Python v1-model maakt gebruik van een functions.json-bestand om functies te definiëren. Met het nieuwe v2-model kunt u in plaats daarvan een op decorator gebaseerde benadering gebruiken. Deze nieuwe benadering resulteert in een eenvoudigere bestandsstructuur en is meer codegericht. Kies de v2-selector bovenaan het artikel voor meer informatie over dit nieuwe programmeermodel.

Als Python-ontwikkelaar bent u mogelijk ook geïnteresseerd in een van de volgende artikelen:

Ontwikkelingsopties

Beide Python Functions-programmeermodellen ondersteunen lokale ontwikkeling in een van de volgende omgevingen:

Python v2-programmeermodel:

Houd er rekening mee dat het Python v2-programmeermodel alleen wordt ondersteund in de runtime van 4.x-functies. Raadpleeg Overzicht van Azure Functions-runtime voor meer informatie.

Python v1-programmeermodel:

U kunt ook Python v1-functies maken in Azure Portal.

Tip

Hoewel u uw Op Python gebaseerde Azure-functies lokaal in Windows kunt ontwikkelen, wordt Python alleen ondersteund in een hostingabonnement op basis van Linux wanneer deze wordt uitgevoerd in Azure. Zie de lijst met ondersteunde combinaties van besturingssystemen/runtime voor meer informatie.

Programmeermodel

Azure Functions verwacht dat een functie een staatloze methode is in uw Python-script dat invoer verwerkt en uitvoer produceert. Standaard verwacht de runtime dat de methode wordt geïmplementeerd als een globale methode die wordt aangeroepen main() in het __init__.py-bestand . U kunt ook een alternatief toegangspunt opgeven.

U koppelt gegevens aan de functie vanuit triggers en bindingen via methodekenmerken die gebruikmaken van de name eigenschap die is gedefinieerd in het function.json bestand. In het volgende function.json bestand wordt bijvoorbeeld een eenvoudige functie beschreven die wordt geactiveerd door een HTTP-aanvraag met de naam req:

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

Op basis van deze definitie kan het __init__.py-bestand met de functiecode eruitzien als in het volgende voorbeeld:

def main(req):
    user = req.params.get('user')
    return f'Hello, {user}!'

U kunt ook expliciet de kenmerktypen declareren en het retourtype in de functie retourneren met behulp van aantekeningen van Python-typen. Dit helpt u bij het gebruik van de IntelliSense- en automatisch aanvullen-functies die worden geleverd door veel Python-code-editors.

import azure.functions

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

Gebruik de Python-aantekeningen die zijn opgenomen in het pakket azure.functions.* om de invoer en uitvoer te binden aan uw methoden.

Azure Functions verwacht dat een functie een staatloze methode is in uw Python-script dat invoer verwerkt en uitvoer produceert. Standaard verwacht de runtime dat de methode wordt geïmplementeerd als een globale methode in het function_app.py-bestand .

Triggers en bindingen kunnen worden gedeclareerd en gebruikt in een functie in een op decorator gebaseerde benadering. Ze worden gedefinieerd in hetzelfde bestand, function_app.py, als de functies. Het volgende function_app.py bestand vertegenwoordigt bijvoorbeeld een functietrigger door een HTTP-aanvraag.

@app.function_name(name="HttpTrigger1")
@app.route(route="req")
def main(req):
    user = req.params.get("user")
    return f"Hello, {user}!"

U kunt ook expliciet de kenmerktypen declareren en het retourtype in de functie retourneren met behulp van aantekeningen van Python-typen. Dit helpt u bij het gebruik van de IntelliSense- en automatisch aanvullen-functies die worden geleverd door veel Python-code-editors.

import azure.functions as func

app = func.FunctionApp()

@app.function_name(name="HttpTrigger1")
@app.route(route="req")
def main(req: func.HttpRequest) -> str:
    user = req.params.get("user")
    return f"Hello, {user}!"

Zie Python-fouten in Azure Functions oplossen voor meer informatie over bekende beperkingen met het v2-model en hun tijdelijke oplossingen.

Alternatief toegangspunt

U kunt het standaardgedrag van een functie wijzigen door desgewenst de scriptFile en entryPoint eigenschappen op te geven in het function.json bestand. Met de volgende function.json geeft u bijvoorbeeld aan dat de runtime de customentry() methode in het main.py-bestand moet gebruiken als het toegangspunt voor uw Azure-functie.

{
  "scriptFile": "main.py",
  "entryPoint": "customentry",
  "bindings": [
      ...
  ]
}

Het toegangspunt bevindt zich alleen in het function_app.py-bestand . U kunt echter verwijzen naar functies in het project in function_app.py met behulp van blauwdrukken of door ze te importeren.

Mapstructuur

De aanbevolen mapstructuur voor een Python Functions-project ziet eruit als in het volgende voorbeeld:

 <project_root>/
 | - .venv/
 | - .vscode/
 | - my_first_function/
 | | - __init__.py
 | | - function.json
 | | - example.py
 | - my_second_function/
 | | - __init__.py
 | | - function.json
 | - shared_code/
 | | - __init__.py
 | | - my_first_helper_function.py
 | | - my_second_helper_function.py
 | - tests/
 | | - test_my_second_function.py
 | - .funcignore
 | - host.json
 | - local.settings.json
 | - requirements.txt
 | - Dockerfile

De hoofdprojectmap, <project_root>, kan de volgende bestanden bevatten:

  • local.settings.json: wordt gebruikt voor het opslaan van app-instellingen en verbindingsreeks s bij het lokaal uitvoeren. Dit bestand wordt niet gepubliceerd naar Azure. Zie local.settings.file voor meer informatie.
  • requirements.txt: Bevat de lijst met Python-pakketten die het systeem installeert bij het publiceren naar Azure.
  • host.json: bevat configuratieopties die van invloed zijn op alle functies in een exemplaar van een functie-app. Dit bestand wordt wel gepubliceerd naar Azure. Niet alle opties worden ondersteund bij lokaal uitvoeren. Zie host.json voor meer informatie.
  • .vscode/: (optioneel) Bevat de opgeslagen Visual Studio Code-configuratie. Zie Visual Studio Code-instellingen voor meer informatie.
  • .venv/: (optioneel) Bevat een virtuele Python-omgeving die wordt gebruikt door lokale ontwikkeling.
  • Dockerfile: (optioneel) Wordt gebruikt bij het publiceren van uw project in een aangepaste container.
  • tests/: (optioneel) Bevat de testcases van uw functie-app.
  • .funcignore: (Optioneel) Declareert bestanden die niet naar Azure mogen worden gepubliceerd. Meestal bevat dit bestand .vscode/ om uw editorinstelling te negeren, .venv/ om de lokale virtuele Python-omgeving te negeren, tests/ testcases te negeren en local.settings.json om te voorkomen dat lokale app-instellingen worden gepubliceerd.

Elke functie heeft een eigen codebestand en bindingsconfiguratiebestand, function.json.

De aanbevolen mapstructuur voor een Python Functions-project ziet eruit als in het volgende voorbeeld:

 <project_root>/
 | - .venv/
 | - .vscode/
 | - function_app.py
 | - additional_functions.py
 | - tests/
 | | - test_my_function.py
 | - .funcignore
 | - host.json
 | - local.settings.json
 | - requirements.txt
 | - Dockerfile

De hoofdprojectmap, <project_root>, kan de volgende bestanden bevatten:

  • .venv/: (optioneel) Bevat een virtuele Python-omgeving die wordt gebruikt door lokale ontwikkeling.
  • .vscode/: (optioneel) Bevat de opgeslagen Visual Studio Code-configuratie. Zie Visual Studio Code-instellingen voor meer informatie.
  • function_app.py: de standaardlocatie voor alle functies en de bijbehorende triggers en bindingen.
  • additional_functions.py: (optioneel) Alle andere Python-bestanden die functies bevatten (meestal voor logische groepering) waarnaar wordt verwezen in function_app.py via blauwdrukken.
  • tests/: (optioneel) Bevat de testcases van uw functie-app.
  • .funcignore: (Optioneel) Declareert bestanden die niet naar Azure mogen worden gepubliceerd. Meestal bevat dit bestand .vscode/ om uw editorinstelling te negeren, .venv/ om lokale virtuele Python-omgeving te negeren, tests/ testcases te negeren en local.settings.json om te voorkomen dat lokale app-instellingen worden gepubliceerd.
  • host.json: bevat configuratieopties die van invloed zijn op alle functies in een exemplaar van een functie-app. Dit bestand wordt wel gepubliceerd naar Azure. Niet alle opties worden ondersteund bij lokaal uitvoeren. Zie host.json voor meer informatie.
  • local.settings.json: wordt gebruikt voor het opslaan van app-instellingen en verbindingsreeks s wanneer deze lokaal wordt uitgevoerd. Dit bestand wordt niet gepubliceerd naar Azure. Zie local.settings.file voor meer informatie.
  • requirements.txt: Bevat de lijst met Python-pakketten die het systeem installeert wanneer het naar Azure publiceert.
  • Dockerfile: (optioneel) Wordt gebruikt bij het publiceren van uw project in een aangepaste container.

Wanneer u uw project implementeert in een functie-app in Azure, moet de volledige inhoud van de hoofdprojectmap, <project_root>, worden opgenomen in het pakket, maar niet in de map zelf, wat betekent dat host.json zich in de hoofdmap van het pakket moet bevinden. U wordt aangeraden uw tests in een map samen met andere functies te onderhouden (in dit voorbeeld testen/). Zie Eenheidstests voor meer informatie.

Verbinding maken met een database

Azure Functions is goed geïntegreerd met Azure Cosmos DB voor veel gebruiksvoorbeelden, waaronder IoT, e-commerce, gaming, enzovoort.

Voor gebeurtenisbronnen zijn de twee services bijvoorbeeld geïntegreerd in gebeurtenisgestuurde architecturen met behulp van de functionaliteit van de wijzigingenfeed van Azure Cosmos DB. De wijzigingenfeed biedt downstream-microservices de mogelijkheid om op betrouwbare en incrementele wijze invoegingen en updates te lezen (bijvoorbeeld ordergebeurtenissen). Deze functionaliteit kan worden gebruikt om een permanent gebeurtenisarchief te bieden als berichtbroker voor status veranderende gebeurtenissen en de werkstroom voor het verwerken van orders tussen veel microservices (die kunnen worden geïmplementeerd als serverloze Azure Functions).

Referentiearchitectuur voor volgordepijplijnen in Azure Cosmos DB

Als u verbinding wilt maken met Cosmos DB, maakt u eerst een account, database en container. Vervolgens kunt u Functies verbinden met Cosmos DB met behulp van triggers en bindingen, zoals in dit voorbeeld.

Als u complexere app-logica wilt implementeren, kunt u ook de Python-bibliotheek voor Cosmos DB gebruiken. Een aynchroneuze I/O-implementatie ziet er als volgt uit:

pip install azure-cosmos
pip install aiohttp

from azure.cosmos.aio import CosmosClient
from azure.cosmos import exceptions
from azure.cosmos.partition_key import PartitionKey
import asyncio

# Replace these values with your Cosmos DB connection information
endpoint = "https://azure-cosmos-nosql.documents.azure.com:443/"
key = "master_key"
database_id = "cosmicwerx"
container_id = "cosmicontainer"
partition_key = "/partition_key"

# Set the total throughput (RU/s) for the database and container
database_throughput = 1000

# Singleton CosmosClient instance
client = CosmosClient(endpoint, credential=key)

# Helper function to get or create database and container
async def get_or_create_container(client, database_id, container_id, partition_key):
    database = await client.create_database_if_not_exists(id=database_id)
    print(f'Database "{database_id}" created or retrieved successfully.')

    container = await database.create_container_if_not_exists(id=container_id, partition_key=PartitionKey(path=partition_key))
    print(f'Container with id "{container_id}" created')
 
    return container
 
async def create_products():
    container = await get_or_create_container(client, database_id, container_id, partition_key)
    for i in range(10):
        await container.upsert_item({
            'id': f'item{i}',
            'productName': 'Widget',
            'productModel': f'Model {i}'
        })
 
async def get_products():
    items = []
    container = await get_or_create_container(client, database_id, container_id, partition_key)
    async for item in container.read_all_items():
        items.append(item)
    return items

async def query_products(product_name):
    container = await get_or_create_container(client, database_id, container_id, partition_key)
    query = f"SELECT * FROM c WHERE c.productName = '{product_name}'"
    items = []
    async for item in container.query_items(query=query, enable_cross_partition_query=True):
        items.append(item)
    return items

async def main():
    await create_products()
    all_products = await get_products()
    print('All Products:', all_products)

    queried_products = await query_products('Widget')
    print('Queried Products:', queried_products)

if __name__ == "__main__":
    asyncio.run(main())

Blueprints

Het Programmeermodel python v2 introduceert het concept van blauwdrukken. Een blauwdruk is een nieuwe klasse die wordt geïnstantieerd om functies buiten de kernfunctietoepassing te registreren. De functies die zijn geregistreerd in blauwdrukexemplaren, worden niet rechtstreeks geïndexeerd door de functieruntime. Om deze blauwdrukfuncties geïndexeerd te krijgen, moet de functie-app de functies registreren bij blauwdrukexemplaren.

Het gebruik van blauwdrukken biedt de volgende voordelen:

  • Hiermee kunt u de functie-app opsplitsen in modulaire onderdelen, waarmee u functies in meerdere Python-bestanden kunt definiëren en deze kunt verdelen in verschillende onderdelen per bestand.
  • Biedt uitbreidbare interfaces voor openbare functie-apps om uw eigen API's te bouwen en opnieuw te gebruiken.

In het volgende voorbeeld ziet u hoe u blauwdrukken gebruikt:

Eerst wordt in een http_blueprint.py-bestand een door HTTP geactiveerde functie gedefinieerd en toegevoegd aan een blauwdrukobject.

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 
        ) 

Vervolgens wordt in het function_app.py-bestand het blauwdrukobject geïmporteerd en worden de bijbehorende functies geregistreerd bij de functie-app.

import azure.functions as func 
from http_blueprint import bp

app = func.FunctionApp() 

app.register_functions(bp) 

Notitie

Durable Functions ondersteunt ook blauwdrukken. Als u blauwdrukken wilt maken voor Durable Functions-apps, registreert u de indeling, activiteit en entiteitstriggers en clientbindingen met behulp van de azure-functions-durableBlueprint klasse, zoals hier wordt weergegeven. De resulterende blauwdruk kan vervolgens als normaal worden geregistreerd. Bekijk ons voorbeeld voor een voorbeeld.

Importgedrag

U kunt modules in uw functiecode importeren met zowel absolute als relatieve verwijzingen. Op basis van de eerder beschreven mapstructuur worden de volgende importbewerkingen uitgevoerd vanuit het functiebestand <project_root>\my_first_function\__init__.py:

from shared_code import my_first_helper_function #(absolute)
import shared_code.my_second_helper_function #(absolute)
from . import example #(relative)

Notitie

Wanneer u de absolute importsyntaxis gebruikt, moet de shared_code/ map een __init__.py-bestand bevatten om het als een Python-pakket te markeren.

De volgende __app__ importeren en verder dan relatieve import op het hoogste niveau zijn afgeschaft, omdat ze niet worden ondersteund door de statische typecontrole en niet worden ondersteund door Python-testframeworks:

from __app__.shared_code import my_first_helper_function #(deprecated __app__ import)
from ..shared_code import my_first_helper_function #(deprecated beyond top-level relative import)

Triggers en invoer

Invoer is onderverdeeld in twee categorieën in Azure Functions: triggerinvoer en andere invoer. Hoewel ze verschillen in het function.json-bestand , is het gebruik ervan identiek in Python-code. Verbinding maken iontekenreeksen of geheimen voor trigger- en invoerbronnen worden toegewezen aan waarden in het local.settings.json-bestand wanneer ze lokaal worden uitgevoerd en worden ze toegewezen aan de toepassingsinstellingen wanneer ze worden uitgevoerd in Azure.

De volgende code laat bijvoorbeeld het verschil zien tussen de twee invoerwaarden:

// function.json
{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "name": "req",
      "direction": "in",
      "type": "httpTrigger",
      "authLevel": "anonymous",
      "route": "items/{id}"
    },
    {
      "name": "obj",
      "direction": "in",
      "type": "blob",
      "path": "samples/{id}",
      "connection": "STORAGE_CONNECTION_STRING"
    }
  ]
}
// local.settings.json
{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "STORAGE_CONNECTION_STRING": "<AZURE_STORAGE_CONNECTION_STRING>",
    "AzureWebJobsStorage": "<azure-storage-connection-string>"
  }
}
# __init__.py
import azure.functions as func
import logging

def main(req: func.HttpRequest, obj: func.InputStream):
    logging.info(f'Python HTTP-triggered function processed: {obj.read()}')

Wanneer de functie wordt aangeroepen, wordt de HTTP-aanvraag als doorgegeven aan de functie req. Er wordt een vermelding opgehaald uit het Azure Blob Storage-account op basis van de id in de route-URL en beschikbaar gemaakt als obj in de hoofdtekst van de functie. Hier is het opgegeven opslagaccount de verbindingsreeks die in de CONNECTION_STRING app-instelling is gevonden.

Invoer is onderverdeeld in twee categorieën in Azure Functions: triggerinvoer en andere invoer. Hoewel ze zijn gedefinieerd met behulp van verschillende decorators, is hun gebruik vergelijkbaar in Python-code. Verbinding maken iontekenreeksen of geheimen voor trigger- en invoerbronnen worden toegewezen aan waarden in het local.settings.json-bestand wanneer ze lokaal worden uitgevoerd en worden ze toegewezen aan de toepassingsinstellingen wanneer ze worden uitgevoerd in Azure.

De volgende code laat bijvoorbeeld zien hoe u een Blob Storage-invoerbinding definieert:

// local.settings.json
{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "STORAGE_CONNECTION_STRING": "<AZURE_STORAGE_CONNECTION_STRING>",
    "AzureWebJobsStorage": "<azure-storage-connection-string>",
    "AzureWebJobsFeatureFlags": "EnableWorkerIndexing"
  }
}
# function_app.py
import azure.functions as func
import logging

app = func.FunctionApp()

@app.route(route="req")
@app.read_blob(arg_name="obj", path="samples/{id}", 
               connection="STORAGE_CONNECTION_STRING")
def main(req: func.HttpRequest, obj: func.InputStream):
    logging.info(f'Python HTTP-triggered function processed: {obj.read()}')

Wanneer de functie wordt aangeroepen, wordt de HTTP-aanvraag als doorgegeven aan de functie req. Er wordt een vermelding opgehaald uit het Azure Blob Storage-account op basis van de id in de route-URL en beschikbaar gemaakt als obj in de hoofdtekst van de functie. Hier is het opgegeven opslagaccount de verbindingsreeks die in de STORAGE_CONNECTION_STRING app-instelling is gevonden.

Voor gegevensintensieve bindingsbewerkingen wilt u mogelijk een afzonderlijk opslagaccount gebruiken. Zie de richtlijnen voor opslagaccounts voor meer informatie.

Uitvoerwaarden

Uitvoer kan zowel in retourwaarde als uitvoerparameters worden uitgedrukt. Als er slechts één uitvoer is, raden we u aan de retourwaarde te gebruiken. Voor meerdere uitvoer moet u uitvoerparameters gebruiken.

Als u de retourwaarde van een functie wilt gebruiken als de waarde van een uitvoerbinding, moet de name eigenschap van de binding worden ingesteld $return op in het function.json bestand.

Als u meerdere uitvoer wilt produceren, gebruikt u de set() methode van de azure.functions.Out interface om een waarde toe te wijzen aan de binding. De volgende functie kan bijvoorbeeld een bericht naar een wachtrij pushen en ook een HTTP-antwoord retourneren.

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "name": "req",
      "direction": "in",
      "type": "httpTrigger",
      "authLevel": "anonymous"
    },
    {
      "name": "msg",
      "direction": "out",
      "type": "queue",
      "queueName": "outqueue",
      "connection": "STORAGE_CONNECTION_STRING"
    },
    {
      "name": "$return",
      "direction": "out",
      "type": "http"
    }
  ]
}
import azure.functions as func

def main(req: func.HttpRequest,
         msg: func.Out[func.QueueMessage]) -> str:

    message = req.params.get('body')
    msg.set(message)
    return message

Uitvoer kan zowel in retourwaarde als uitvoerparameters worden uitgedrukt. Als er slechts één uitvoer is, raden we u aan de retourwaarde te gebruiken. Voor meerdere uitvoer moet u uitvoerparameters gebruiken.

Als u meerdere uitvoer wilt produceren, gebruikt u de set() methode van de azure.functions.Out interface om een waarde toe te wijzen aan de binding. De volgende functie kan bijvoorbeeld een bericht naar een wachtrij pushen en ook een HTTP-antwoord retourneren.

# function_app.py
import azure.functions as func

app = func.FunctionApp()

@app.write_blob(arg_name="msg", path="output-container/{name}",
                connection="CONNECTION_STRING")
def test_function(req: func.HttpRequest,
                  msg: func.Out[str]) -> str:

    message = req.params.get('body')
    msg.set(message)
    return message

Logboekregistratie

Toegang tot de Azure Functions Runtime-logboekregistratie is beschikbaar via een hoofdhandler logging in uw functie-app. Deze logboekregistratie is gekoppeld aan Application Insights en stelt u in staat waarschuwingen en fouten te markeren die optreden tijdens de uitvoering van de functie.

In het volgende voorbeeld wordt een informatiebericht in een logboek opgeslagen wanneer de functie wordt aangeroepen via een HTTP-trigger.

import logging

def main(req):
    logging.info('Python HTTP trigger function processed a request.')

Er zijn meer logboekregistratiemethoden beschikbaar waarmee u op verschillende traceringsniveaus naar de console kunt schrijven:

Wijze Description
critical(_message_) Hiermee schrijft u een bericht met niveau KRITIEK op de hoofdlogger.
error(_message_) Hiermee schrijft u een bericht met niveau ERROR op de hoofdlogger.
warning(_message_) Hiermee schrijft u een bericht met niveau WAARSCHUWING op de hoofdlogger.
info(_message_) Hiermee schrijft u een bericht met informatie op niveau over de hoofdlogger.
debug(_message_) Hiermee schrijft u een bericht met foutopsporing op niveau DEBUG in de hoofdlogger.

Zie Azure Functions bewaken voor meer informatie over logboekregistratie.

Logboekregistratie van gemaakte threads

Als u wilt zien welke logboeken afkomstig zijn van uw gemaakte threads, neemt u het context argument op in de handtekening van de functie. Dit argument bevat een kenmerk thread_local_storage waarin een lokale invocation_idlocatie wordt opgeslagen. Dit kan worden ingesteld op de huidige van invocation_id de functie om ervoor te zorgen dat de context wordt gewijzigd.

import azure.functions as func
import logging
import threading


def main(req, context):
    logging.info('Python HTTP trigger function processed a request.')
    t = threading.Thread(target=log_function, args=(context,))
    t.start()


def log_function(context):
    context.thread_local_storage.invocation_id = context.invocation_id
    logging.info('Logging from thread.')

Aangepaste telemetrielogboeken

De Functions-runtime verzamelt standaard logboeken en andere telemetriegegevens die door uw functies worden gegenereerd. Deze telemetrie komt terecht als traceringen in Application Insights. De telemetrie van aanvragen en afhankelijkheden voor bepaalde Azure-services wordt ook standaard verzameld door triggers en bindingen.

Als u aangepaste aanvragen en aangepaste afhankelijkheidstelemetrie buiten bindingen wilt verzamelen, kunt u de OpenCensus Python-extensies gebruiken. Met deze extensie worden aangepaste telemetriegegevens naar uw Application Insights-exemplaar verzonden. U vindt een lijst met ondersteunde extensies in de OpenCensus-opslagplaats.

Notitie

Als u de OpenCensus Python-extensies wilt gebruiken, moet u Python-werkrolextensies inschakelen in uw functie-app door in te stellen PYTHON_ENABLE_WORKER_EXTENSIONS op 1. U moet ook overschakelen naar het gebruik van de Application Insights-verbindingsreeks door de APPLICATIONINSIGHTS_CONNECTION_STRING instelling toe te voegen aan uw toepassingsinstellingen, als deze nog niet aanwezig is.

// requirements.txt
...
opencensus-extension-azure-functions
opencensus-ext-requests
import json
import logging

import requests
from opencensus.extension.azure.functions import OpenCensusExtension
from opencensus.trace import config_integration

config_integration.trace_integrations(['requests'])

OpenCensusExtension.configure()

def main(req, context):
    logging.info('Executing HttpTrigger with OpenCensus extension')

    # You must use context.tracer to create spans
    with context.tracer.span("parent"):
        response = requests.get(url='http://example.com')

    return json.dumps({
        'method': req.method,
        'response': response.status_code,
        'ctx_func_name': context.function_name,
        'ctx_func_dir': context.function_directory,
        'ctx_invocation_id': context.invocation_id,
        'ctx_trace_context_Traceparent': context.trace_context.Traceparent,
        'ctx_trace_context_Tracestate': context.trace_context.Tracestate,
        'ctx_retry_context_RetryCount': context.retry_context.retry_count,
        'ctx_retry_context_MaxRetryCount': context.retry_context.max_retry_count,
    })

HTTP-trigger

De HTTP-trigger wordt gedefinieerd in het function.json-bestand . De name binding moet overeenkomen met de benoemde parameter in de functie. In de vorige voorbeelden wordt een bindingsnaam req gebruikt. Deze parameter is een HttpRequest-object en er wordt een HttpResponse-object geretourneerd.

Vanuit het HttpRequest-object kunt u aanvraagheaders, queryparameters, routeparameters en de berichttekst ophalen.

Het volgende voorbeeld is afkomstig van de HTTP-triggersjabloon voor Python.

def main(req: func.HttpRequest) -> func.HttpResponse:
    headers = {"my-http-header": "some-value"}

    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}!", headers=headers)
    else:
        return func.HttpResponse(
             "Please pass a name on the query string or in the request body",
             headers=headers, status_code=400
        )

In deze functie haalt u de waarde van de name queryparameter op uit de params parameter van het HttpRequest-object . U leest de hoofdtekst van het JSON-gecodeerde bericht met behulp van de get_json methode.

Op dezelfde manier kunt u het status_code en headers voor het antwoordbericht instellen in het geretourneerde HttpResponse-object .

De HTTP-trigger wordt gedefinieerd als een methode die een benoemde bindingsparameter gebruikt. Dit is een HttpRequest-object en retourneert een HttpResponse-object . U past de function_name decorator toe op de methode om de functienaam te definiëren, terwijl het HTTP-eindpunt is ingesteld door de route decorator toe te passen.

Dit voorbeeld is afkomstig uit de HTTP-triggersjabloon voor het Python v2-programmeermodel, waarbij de naam van de bindingsparameter is req. Dit is de voorbeeldcode die wordt opgegeven wanneer u een functie maakt met behulp van Azure Functions Core Tools of Visual Studio Code.

@app.function_name(name="HttpTrigger1")
@app.route(route="hello")
def test_function(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 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
        )

Vanuit het HttpRequest-object kunt u aanvraagheaders, queryparameters, routeparameters en de berichttekst ophalen. In deze functie haalt u de waarde van de name queryparameter op uit de params parameter van het HttpRequest-object . U leest de hoofdtekst van het JSON-gecodeerde bericht met behulp van de get_json methode.

Op dezelfde manier kunt u het status_code en headers voor het antwoordbericht instellen in het geretourneerde HttpResponse-object .

Als u een naam in dit voorbeeld wilt doorgeven, plakt u de URL die wordt opgegeven wanneer u de functie uitvoert en voegt u deze vervolgens toe aan "?name={name}".

Webframeworks

U kunt Web Server Gateway Interface (WSGI)-compatibele en Asynchrone Server Gateway Interface (ASGI)-compatibele frameworks, zoals Flask en FastAPI, gebruiken met uw door HTTP geactiveerde Python-functies. In deze sectie wordt beschreven hoe u uw functies kunt wijzigen ter ondersteuning van deze frameworks.

Eerst moet het function.json-bestand worden bijgewerkt om een route in de HTTP-trigger op te nemen, zoals wordt weergegeven in het volgende voorbeeld:

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
       "authLevel": "anonymous",
       "type": "httpTrigger",
       "direction": "in",
       "name": "req",
       "methods": [
           "get",
           "post"
       ],
       "route": "{*route}"
    },
    {
       "type": "http",
       "direction": "out",
       "name": "$return"
    }
  ]
}

Het host.json-bestand moet ook worden bijgewerkt om een HTTP-bestand routePrefixop te nemen, zoals wordt weergegeven in het volgende voorbeeld:

{
  "version": "2.0",
  "logging": 
  {
    "applicationInsights": 
    {
      "samplingSettings": 
      {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": 
  {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[3.*, 4.0.0)"
  },
  "extensions": 
  {
    "http": 
    {
        "routePrefix": ""
    }
  }
}

Werk het Python-codebestand init.py bij, afhankelijk van de interface die door uw framework wordt gebruikt. In het volgende voorbeeld ziet u een ASGI-handlerbenadering of een WSGI-wrapper-benadering voor Flask:

app = fastapi.FastAPI()

@app.get("hello/{name}")
async def get_name(name: str):
  return {"name": name}

def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
    return func.AsgiMiddleware(app).handle(req, context)

U kunt Asynchrone Server Gateway Interface (ASGI)-compatibele frameworks (Web Server Gateway Interface, WSGI) gebruiken, zoals Flask en FastAPI, met uw door HTTP geactiveerde Python-functies. U moet eerst het host.json-bestand bijwerken om een HTTP-bestand routePrefixop te nemen, zoals wordt weergegeven in het volgende voorbeeld:

{
  "version": "2.0",
  "logging": 
  {
    "applicationInsights": 
    {
      "samplingSettings": 
      {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": 
  {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[2.*, 3.0.0)"
  },
  "extensions": 
  {
    "http": 
    {
        "routePrefix": ""
    }
  }
}

De frameworkcode ziet eruit als in het volgende voorbeeld:

AsgiFunctionApp is de klasse van de functie-app op het hoogste niveau voor het maken van ASGI HTTP-functies.

# 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) 

Schalen en prestaties

Zie het artikel over schalen en prestaties voor Python-functie-apps voor aanbevolen procedures voor schalen en prestaties van Python.

Context

Als u de aanroepcontext van een functie wilt ophalen wanneer deze wordt uitgevoerd, neemt u het argument op in de context handtekening.

Voorbeeld:

import azure.functions


def main(req: azure.functions.HttpRequest,
         context: azure.functions.Context) -> str:
    return f'{context.invocation_id}'

De Context klasse heeft de volgende tekenreekskenmerken:

Kenmerk Beschrijving
function_directory De map waarin de functie wordt uitgevoerd.
function_name De naam van de functie.
invocation_id De id van de huidige functie-aanroep.
thread_local_storage De lokale threadopslag van de functie. Bevat een lokaal invocation_id bestand voor logboekregistratie op basis van gemaakte threads.
trace_context De context voor gedistribueerde tracering. Zie Trace Context voor meer informatie.
retry_context De context voor nieuwe pogingen naar de functie. Zie retry-policies voor meer informatie.

Algemene variabelen

Het is niet gegarandeerd dat de status van uw app behouden blijft voor toekomstige uitvoeringen. De Azure Functions-runtime gebruikt echter vaak hetzelfde proces voor meerdere uitvoeringen van dezelfde app. Als u de resultaten van een dure berekening in de cache wilt opslaan, declareert u deze als een globale variabele.

CACHED_DATA = None


def main(req):
    global CACHED_DATA
    if CACHED_DATA is None:
        CACHED_DATA = load_json()

    # ... use CACHED_DATA in code

Omgevingsvariabelen

In Azure Functions worden toepassingsinstellingen, zoals service-verbindingsreeks s, weergegeven als omgevingsvariabelen wanneer ze worden uitgevoerd. Er zijn twee manieren om toegang te krijgen tot deze instellingen in uw code.

Wijze Description
os.environ["myAppSetting"] Probeert de toepassingsinstelling op sleutelnaam op te halen en genereert een fout wanneer deze niet lukt.
os.getenv("myAppSetting") Probeert de toepassingsinstelling op sleutelnaam op te halen en wordt geretourneerd null wanneer deze niet lukt.

Voor beide manieren moet u declareren import os.

In het volgende voorbeeld wordt os.environ["myAppSetting"] de toepassingsinstelling getypt, met de sleutel met de naam myAppSetting:

import logging
import os

import azure.functions as func

def main(req: func.HttpRequest) -> func.HttpResponse:
  # Get the setting named 'myAppSetting'
  my_app_setting_value = os.environ["myAppSetting"]
  logging.info(f'My app setting value:{my_app_setting_value}')

Voor lokale ontwikkeling worden toepassingsinstellingen onderhouden in het local.settings.json-bestand.

In Azure Functions worden toepassingsinstellingen, zoals service-verbindingsreeks s, weergegeven als omgevingsvariabelen wanneer ze worden uitgevoerd. Er zijn twee manieren om toegang te krijgen tot deze instellingen in uw code.

Wijze Description
os.environ["myAppSetting"] Probeert de toepassingsinstelling op sleutelnaam op te halen en genereert een fout wanneer deze niet lukt.
os.getenv("myAppSetting") Probeert de toepassingsinstelling op sleutelnaam op te halen en wordt geretourneerd null wanneer deze niet lukt.

Voor beide manieren moet u declareren import os.

In het volgende voorbeeld wordt os.environ["myAppSetting"] de toepassingsinstelling getypt, met de sleutel met de naam myAppSetting:

import logging
import os

import azure.functions as func

app = func.FunctionApp()

@app.function_name(name="HttpTrigger1")
@app.route(route="req")
def main(req: func.HttpRequest) -> func.HttpResponse:
  # Get the setting named 'myAppSetting'
  my_app_setting_value = os.environ["myAppSetting"]
  logging.info(f'My app setting value:{my_app_setting_value}')

Voor lokale ontwikkeling worden toepassingsinstellingen onderhouden in het local.settings.json-bestand.

Wanneer u het nieuwe programmeermodel gebruikt, schakelt u de volgende app-instelling in het bestand local.settings.json in, zoals hier wordt weergegeven:

"AzureWebJobsFeatureFlags": "EnableWorkerIndexing"

Wanneer u de functie implementeert, wordt deze instelling niet automatisch gemaakt. U moet deze instelling expliciet maken in uw functie-app in Azure om deze te kunnen uitvoeren met behulp van het v2-model.

Python-versie

Azure Functions ondersteunt de volgende Python-versies:

Functions-versie Python*-versies
4.x 3.11
3.10
3.9
3.8
3.7
3.x 3.9
3.8
3.7

* Officiële Python-distributies

Als u een specifieke Python-versie wilt aanvragen wanneer u uw functie-app in Azure maakt, gebruikt u de --runtime-version optie van de az functionapp create opdracht. De runtimeversie van Functions wordt ingesteld door de --functions-version optie. De Python-versie wordt ingesteld wanneer de functie-app wordt gemaakt en kan niet worden gewijzigd voor apps die worden uitgevoerd in een verbruiksabonnement.

De runtime gebruikt de beschikbare Python-versie wanneer u deze lokaal uitvoert.

Python-versie wijzigen

Als u een Python-functie-app wilt instellen op een specifieke taalversie, moet u de taal en de versie van de taal in het LinuxFxVersion veld in de siteconfiguratie opgeven. Als u bijvoorbeeld de Python-app wilt wijzigen voor het gebruik van Python 3.8, stelt u deze in linuxFxVersion op python|3.8.

Zie Runtime-versies van Azure Functions als u wilt weten hoe u de linuxFxVersion site-instelling kunt bekijken en wijzigen.

Zie het ondersteuningsbeleid voor Azure Functions-runtime en ondersteunde talen in Azure Functions voor meer algemene informatie.

Pakketbeheer

Wanneer u lokaal ontwikkelt met behulp van Core Tools of Visual Studio Code, voegt u de namen en versies van de vereiste pakketten toe aan het requirements.txt-bestand en installeert u deze vervolgens met behulp van pip.

U kunt bijvoorbeeld het volgende requirements.txt bestand en pip de volgende opdracht gebruiken om het requests pakket te installeren vanuit PyPI.

requests==2.19.1
pip install -r requirements.txt

Wanneer u uw functies uitvoert in een App Service-plan, krijgen afhankelijkheden die u in requirements.txt definieert voorrang op ingebouwde Python-modules, zoals logging. Deze prioriteit kan conflicten veroorzaken wanneer ingebouwde modules dezelfde namen hebben als mappen in uw code. Wanneer u een verbruiksabonnement of een Elastic Premium-abonnement uitvoert, zijn conflicten minder waarschijnlijk omdat uw afhankelijkheden niet standaard prioriteit hebben.

Als u problemen wilt voorkomen die worden uitgevoerd in een App Service-plan, geeft u uw mappen niet dezelfde naam als systeemeigen Python-modules en neemt u geen systeemeigen Python-bibliotheken op in het requirements.txt-bestand van uw project.

Publiceren naar Azure

Wanneer u klaar bent om te publiceren, moet u ervoor zorgen dat al uw openbaar beschikbare afhankelijkheden worden vermeld in het requirements.txt-bestand . U kunt dit bestand vinden in de hoofdmap van uw projectmap.

U vindt de projectbestanden en -mappen die zijn uitgesloten van publicatie, inclusief de map virtuele omgeving, in de hoofdmap van uw project.

Er worden drie buildacties ondersteund voor het publiceren van uw Python-project naar Azure: externe build, lokale build en builds met behulp van aangepaste afhankelijkheden.

U kunt ook Azure Pipelines gebruiken om uw afhankelijkheden te bouwen en te publiceren met behulp van continue levering (CD). Zie Continue levering met Azure Pipelines voor meer informatie.

Externe build

Wanneer u externe build gebruikt, komen afhankelijkheden die zijn hersteld op de server en systeemeigen afhankelijkheden overeen met de productieomgeving. Dit resulteert in een kleiner te uploaden implementatiepakket. Gebruik externe build wanneer u Python-apps in Windows ontwikkelt. Als uw project aangepaste afhankelijkheden heeft, kunt u externe build gebruiken met een extra index-URL.

Afhankelijkheden worden op afstand verkregen op basis van de inhoud van het requirements.txt-bestand . Externe build is de aanbevolen buildmethode. Core Tools vraagt standaard een externe build aan wanneer u de volgende func azure functionapp publish opdracht gebruikt om uw Python-project naar Azure te publiceren.

func azure functionapp publish <APP_NAME>

Vergeet niet om deze te vervangen door <APP_NAME> de naam van uw functie-app in Azure.

De Azure Functions-extensie voor Visual Studio Code vraagt standaard ook een externe build aan.

Lokale build

Afhankelijkheden worden lokaal verkregen op basis van de inhoud van het requirements.txt-bestand . U kunt voorkomen dat een externe build wordt uitgevoerd met behulp van de volgende func azure functionapp publish opdracht om te publiceren met een lokale build:

func azure functionapp publish <APP_NAME> --build local

Vergeet niet om deze te vervangen door <APP_NAME> de naam van uw functie-app in Azure.

Wanneer u de --build local optie gebruikt, worden projectafhankelijkheden gelezen uit het requirements.txt-bestand en worden deze afhankelijke pakketten lokaal gedownload en geïnstalleerd. Projectbestanden en afhankelijkheden worden geïmplementeerd van uw lokale computer naar Azure. Dit resulteert in een groter implementatiepakket dat naar Azure wordt geüpload. Als u om een of andere reden het requirements.txt bestand niet kunt ophalen met Behulp van Core Tools, moet u de optie aangepaste afhankelijkheden gebruiken voor het publiceren.

Het wordt afgeraden lokale builds te gebruiken wanneer u lokaal ontwikkelt in Windows.

Aangepaste afhankelijkheden

Wanneer uw project afhankelijkheden bevat die niet zijn gevonden in de Python Package Index, zijn er twee manieren om het project te bouwen. De eerste manier, de buildmethode , is afhankelijk van hoe u het project bouwt.

Externe build met extra index-URL

Wanneer uw pakketten beschikbaar zijn vanuit een toegankelijke aangepaste pakketindex, gebruikt u een externe build. Voordat u publiceert, moet u een app-instelling met de naam PIP_EXTRA_INDEX_URLmaken. De waarde voor deze instelling is de URL van uw aangepaste pakketindex. Als u deze instelling gebruikt, moet de externe build worden uitgevoerd pip install met behulp van de --extra-index-url optie. Zie de Python-documentatie pip installvoor meer informatie.

U kunt ook basisverificatiereferenties gebruiken met uw extra URL's voor pakketindexen. Zie basisverificatiereferenties in de Python-documentatie voor meer informatie.

Lokale pakketten installeren

Als uw project pakketten gebruikt die niet openbaar beschikbaar zijn voor onze hulpprogramma's, kunt u ze beschikbaar maken voor uw app door ze in de map __app__/.python_packages te plaatsen. Voordat u publiceert, voert u de volgende opdracht uit om de afhankelijkheden lokaal te installeren:

pip install  --target="<PROJECT_DIR>/.python_packages/lib/site-packages"  -r requirements.txt

Wanneer u aangepaste afhankelijkheden gebruikt, moet u de --no-build publicatieoptie gebruiken, omdat u de afhankelijkheden al in de projectmap hebt geïnstalleerd.

func azure functionapp publish <APP_NAME> --no-build

Vergeet niet om deze te vervangen door <APP_NAME> de naam van uw functie-app in Azure.

Het testen van modules

Functies die zijn geschreven in Python, kunnen worden getest als andere Python-code met behulp van standaard testframeworks. Voor de meeste bindingen is het mogelijk om een mock-invoerobject te maken door een exemplaar van een geschikte klasse te maken op basis van het azure.functions pakket. Aangezien het azure.functions pakket niet onmiddellijk beschikbaar is, moet u het installeren via uw requirements.txt-bestand , zoals beschreven in de sectie pakketbeheer hierboven.

Met my_second_function als voorbeeld is het volgende een mocktest van een door HTTP geactiveerde functie:

Maak eerst een <bestand project_root>/my_second_function/function.json en definieer deze functie vervolgens als een HTTP-trigger.

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

Vervolgens kunt u implementeren my_second_function en shared_code.my_second_helper_function.

# <project_root>/my_second_function/__init__.py
import azure.functions as func
import logging

# Use absolute import to resolve shared_code modules
from shared_code import my_second_helper_function

# Define an HTTP trigger that accepts the ?value=<int> query parameter
# Double the value and return the result in HttpResponse
def main(req: func.HttpRequest) -> func.HttpResponse:
  logging.info('Executing my_second_function.')

  initial_value: int = int(req.params.get('value'))
  doubled_value: int = my_second_helper_function.double(initial_value)

  return func.HttpResponse(
    body=f"{initial_value} * 2 = {doubled_value}",
    status_code=200
    )
# <project_root>/shared_code/__init__.py
# Empty __init__.py file marks shared_code folder as a Python package
# <project_root>/shared_code/my_second_helper_function.py

def double(value: int) -> int:
  return value * 2

U kunt beginnen met het schrijven van testcases voor uw HTTP-trigger.

# <project_root>/tests/test_my_second_function.py
import unittest

import azure.functions as func
from my_second_function import main

class TestFunction(unittest.TestCase):
  def test_my_second_function(self):
    # Construct a mock HTTP request.
    req = func.HttpRequest(method='GET',
                           body=None,
                           url='/api/my_second_function',
                           params={'value': '21'})
    # Call the function.
    resp = main(req)

    # Check the output.
    self.assertEqual(resp.get_body(), b'21 * 2 = 42',)

Installeer uw favoriete Python-testframework in de map met virtuele Python-omgevingen, zoals pip install pytest. Voer vervolgens uit pytest tests om het testresultaat te controleren.

Maak eerst het <bestand project_root>/function_app.py en implementeer de my_second_function functie als http-trigger en shared_code.my_second_helper_function.

# <project_root>/function_app.py
import azure.functions as func
import logging

# Use absolute import to resolve shared_code modules
from shared_code import my_second_helper_function

app = func.FunctionApp()

# Define the HTTP trigger that accepts the ?value=<int> query parameter
# Double the value and return the result in HttpResponse
@app.function_name(name="my_second_function")
@app.route(route="hello")
def main(req: func.HttpRequest) -> func.HttpResponse:
    logging.info('Executing my_second_function.')

    initial_value: int = int(req.params.get('value'))
    doubled_value: int = my_second_helper_function.double(initial_value)

    return func.HttpResponse(
        body=f"{initial_value} * 2 = {doubled_value}",
        status_code=200
    )
# <project_root>/shared_code/__init__.py
# Empty __init__.py file marks shared_code folder as a Python package
# <project_root>/shared_code/my_second_helper_function.py

def double(value: int) -> int:
  return value * 2

U kunt beginnen met het schrijven van testcases voor uw HTTP-trigger.

# <project_root>/tests/test_my_second_function.py
import unittest
import azure.functions as func

from function_app import main

class TestFunction(unittest.TestCase):
  def test_my_second_function(self):
    # Construct a mock HTTP request.
    req = func.HttpRequest(method='GET',
                           body=None,
                           url='/api/my_second_function',
                           params={'value': '21'})
    # Call the function.
    func_call = main.build().get_user_function()
    resp = func_call(req)
    # Check the output.
    self.assertEqual(
        resp.get_body(),
        b'21 * 2 = 42',
    )

Installeer uw favoriete Python-testframework in de map met virtuele Python-omgevingen, zoals pip install pytest. Voer vervolgens uit pytest tests om het testresultaat te controleren.

Tijdelijke bestanden

De tempfile.gettempdir() methode retourneert een tijdelijke map, die in Linux /tmp is. Uw toepassing kan deze map gebruiken om tijdelijke bestanden op te slaan die worden gegenereerd en gebruikt door uw functies wanneer ze worden uitgevoerd.

Belangrijk

Bestanden die naar de tijdelijke map zijn geschreven, blijven niet gegarandeerd behouden in aanroepen. Tijdens uitschalen worden tijdelijke bestanden niet gedeeld tussen exemplaren.

In het volgende voorbeeld wordt een benoemd tijdelijk bestand gemaakt in de tijdelijke map (/tmp):

import logging
import azure.functions as func
import tempfile

from os import listdir

#---
   tempFilePath = tempfile.gettempdir()
   fp = tempfile.NamedTemporaryFile()
   fp.write(b'Hello world!')
   filesDirListInTemp = listdir(tempFilePath)

U wordt aangeraden uw tests te onderhouden in een map die gescheiden is van de projectmap. Met deze actie kunt u geen testcode met uw app implementeren.

Vooraf geïnstalleerde bibliotheken

Een aantal bibliotheken worden geleverd met de Python Functions Runtime.

De standaardbibliotheek van Python

De standaardbibliotheek van Python bevat een lijst met ingebouwde Python-modules die bij elke Python-distributie worden geleverd. De meeste van deze bibliotheken helpen u toegang te krijgen tot systeemfunctionaliteit, zoals bestandsinvoer/uitvoer (I/O). Op Windows-systemen worden deze bibliotheken geïnstalleerd met Python. Op Unix-systemen worden ze geleverd door pakketverzamelingen.

Als u de bibliotheek voor uw Python-versie wilt weergeven, gaat u naar:

Azure Functions Python-werkafhankelijkheden

Voor de Python-werkrol van Azure Functions is een specifieke set bibliotheken vereist. U kunt deze bibliotheken ook gebruiken in uw functies, maar ze maken geen deel uit van de Python-standaard. Als uw functies afhankelijk zijn van een van deze bibliotheken, zijn deze mogelijk niet beschikbaar voor uw code wanneer deze buiten Azure Functions wordt uitgevoerd. U vindt een gedetailleerde lijst met afhankelijkheden in de sectie 'install_requires' van het setup.py-bestand.

Notitie

Als het requirements.txt-bestand van uw functie-app een azure-functions-worker vermelding bevat, verwijdert u het. De functions-werkrol wordt automatisch beheerd door het Azure Functions-platform en we werken deze regelmatig bij met nieuwe functies en oplossingen voor fouten. Het handmatig installeren van een oude versie van worker in het requirements.txt-bestand kan onverwachte problemen veroorzaken.

Notitie

Als uw pakket bepaalde bibliotheken bevat die kunnen botsen met afhankelijkheden van werkrollen (bijvoorbeeld protobuf, tensorflow of grpcio), configureert u PYTHON_ISOLATE_WORKER_DEPENDENCIES deze 1 in app-instellingen om te voorkomen dat uw toepassing verwijst naar afhankelijkheden van werknemers.

De Python-bibliotheek van Azure Functions

Elke Python-werkrolupdate bevat een nieuwe versie van de Azure Functions Python-bibliotheek (azure.functions). Deze aanpak maakt het eenvoudiger om uw Python-functie-apps continu bij te werken, omdat elke update achterwaarts compatibel is. Ga naar azure-functions PyPi voor een lijst met releases van deze bibliotheek.

De runtimebibliotheekversie is opgelost door Azure en kan niet worden overschreven door requirements.txt. De azure-functions vermelding in requirements.txt is alleen bedoeld voor linting en klantbewustzijn.

Gebruik de volgende code om de werkelijke versie van de Python-functiebibliotheek in uw runtime bij te houden:

getattr(azure.functions, '__version__', '< 1.2.1')

Runtimesysteembibliotheken

Zie het volgende voor een lijst met vooraf geïnstalleerde systeembibliotheken in Docker-installatiekopieën voor Python-werkrollen:

Functions-runtime Debian-versie Python-versies
Versie 3.x Buster Python 3.7
Python 3.8
Python 3.9

Python-werkrolextensies

Met het Python-werkproces dat in Azure Functions wordt uitgevoerd, kunt u bibliotheken van derden integreren in uw functie-app. Deze extensiebibliotheken fungeren als middleware die specifieke bewerkingen kan injecteren tijdens de levenscyclus van de uitvoering van uw functie.

Extensies worden geïmporteerd in uw functiecode, net als een standaardmodule voor Python-bibliotheken. Extensies worden uitgevoerd op basis van de volgende bereiken:

Bereik Beschrijving
Toepassingsniveau Wanneer de extensie wordt geïmporteerd in een functietrigger, is de extensie van toepassing op elke uitvoering van de functie in de app.
Functieniveau Uitvoering is beperkt tot alleen de specifieke functietrigger waarin deze wordt geïmporteerd.

Bekijk de informatie voor elke extensie voor meer informatie over het bereik waarin de extensie wordt uitgevoerd.

Extensies implementeren een Python-werkuitbreidingsinterface. Met deze actie kan het Python-werkproces de extensiecode aanroepen tijdens de uitvoeringslevenscyclus van de functie. Zie Extensies maken voor meer informatie.

Extensies gebruiken

U kunt als volgt een Python-werkuitbreidingsbibliotheek in uw Python-functies gebruiken:

  1. Voeg het extensiepakket toe aan het requirements.txt-bestand voor uw project.
  2. Installeer de bibliotheek in uw app.
  3. Voeg de volgende toepassingsinstellingen toe:
  4. Importeer de extensiemodule in uw functietrigger.
  5. Configureer indien nodig het extensie-exemplaar. Configuratievereisten moeten worden aangeroepen in de documentatie van de extensie.

Belangrijk

Externe Python-werkuitbreidingsbibliotheken worden niet ondersteund of gegarandeerd door Microsoft. U moet ervoor zorgen dat extensies die u in uw functie-app gebruikt, betrouwbaar zijn en u het volledige risico loopt om een schadelijke of slecht geschreven extensie te gebruiken.

Derden moeten specifieke documentatie verstrekken over het installeren en gebruiken van hun extensies in uw functie-app. Zie Uw extensie gebruiken voor een eenvoudig voorbeeld van het gebruik van een extensie.

Hier volgen voorbeelden van het gebruik van extensies in een functie-app, per bereik:

# <project_root>/requirements.txt
application-level-extension==1.0.0
# <project_root>/Trigger/__init__.py

from application_level_extension import AppExtension
AppExtension.configure(key=value)

def main(req, context):
  # Use context.app_ext_attributes here

Extensies maken

Extensies worden gemaakt door bibliotheekontwikkelaars van derden die functionaliteit hebben gemaakt die kan worden geïntegreerd in Azure Functions. Een extensieontwikkelaar ontwerpt, implementeert en publiceert Python-pakketten die aangepaste logica bevatten die speciaal is ontworpen om te worden uitgevoerd in de context van de uitvoering van de functie. Deze extensies kunnen worden gepubliceerd naar het PyPI-register of naar GitHub-opslagplaatsen.

Zie Python-werkuitbreidingen ontwikkelen voor Azure Functions voor meer informatie over het maken, verpakken, publiceren en gebruiken van een Python-werkuitbreidingspakket.

Extensies op toepassingsniveau

Een extensie die wordt overgenomen van AppExtensionBase uitvoeringen in een toepassingsbereik .

AppExtensionBase maakt de volgende abstracte klassemethoden beschikbaar die u kunt implementeren:

Wijze Description
init Aangeroepen nadat de extensie is geïmporteerd.
configure Aangeroepen vanuit functiecode wanneer deze nodig is om de extensie te configureren.
post_function_load_app_level Aangeroepen direct nadat de functie is geladen. De functienaam en de functiemap worden doorgegeven aan de extensie. Houd er rekening mee dat de functiemap alleen-lezen is en dat een poging om naar een lokaal bestand in deze map te schrijven mislukt.
pre_invocation_app_level Aangeroepen vlak voordat de functie wordt geactiveerd. De argumenten voor functiecontext en functie-aanroep worden doorgegeven aan de extensie. Meestal kunt u andere kenmerken doorgeven in het contextobject om de functiecode te gebruiken.
post_invocation_app_level Aangeroepen direct nadat de uitvoering van de functie is voltooid. De functiecontext, argumenten voor functie-aanroep en retourobject voor aanroepen worden doorgegeven aan de extensie. Deze implementatie is een goede plek om te controleren of de uitvoering van de levenscyclushook is geslaagd.

Extensies op functieniveau

Een extensie die wordt overgenomen van FuncExtensionBase wordt uitgevoerd in een specifieke functietrigger.

FuncExtensionBase maakt de volgende abstracte klassemethoden beschikbaar voor implementaties:

Wijze Description
__init__ De constructor van de extensie. Deze wordt aangeroepen wanneer een extensie-exemplaar wordt geïnitialiseerd in een specifieke functie. Wanneer u deze abstracte methode implementeert, wilt u mogelijk een filename parameter accepteren en doorgeven aan de methode super().__init__(filename) van het bovenliggende item voor de juiste extensieregistratie.
post_function_load Aangeroepen direct nadat de functie is geladen. De functienaam en de functiemap worden doorgegeven aan de extensie. Houd er rekening mee dat de functiemap alleen-lezen is en dat een poging om naar een lokaal bestand in deze map te schrijven mislukt.
pre_invocation Aangeroepen vlak voordat de functie wordt geactiveerd. De argumenten voor functiecontext en functie-aanroep worden doorgegeven aan de extensie. Meestal kunt u andere kenmerken doorgeven in het contextobject om de functiecode te gebruiken.
post_invocation Aangeroepen direct nadat de uitvoering van de functie is voltooid. De functiecontext, argumenten voor functie-aanroep en retourobject voor aanroepen worden doorgegeven aan de extensie. Deze implementatie is een goede plek om te controleren of de uitvoering van de levenscyclushook is geslaagd.

Cross-origin-resources delen

Azure Functions biedt ondersteuning voor cross-origin resource sharing (CORS). CORS wordt geconfigureerd in de portal en via de Azure CLI. De lijst met toegestane cors-origins is van toepassing op het niveau van de functie-app. Als CORS is ingeschakeld, bevatten antwoorden de Access-Control-Allow-Origin header. Zie voor meer informatie Cross-origin-resources delen.

CorS (Cross-Origin Resource Sharing) wordt volledig ondersteund voor Python-functie-apps.

Async

Standaard kan een hostexemplaren voor Python slechts één functie aanroepen tegelijk verwerken. Dit komt doordat Python een runtime met één thread is. Voor een functie-app die een groot aantal I/O-gebeurtenissen verwerkt of I/O-gebonden is, kunt u de prestaties aanzienlijk verbeteren door functies asynchroon uit te voeren. Zie Verbeteren in de prestaties van Python-apps in Azure Functions voor meer informatie.

Gedeeld geheugen (preview)

Om de doorvoer te verbeteren, laat Azure Functions uw out-of-process Python language worker geheugen delen met het Functions-hostproces. Wanneer uw functie-app knelpunten raakt, kunt u gedeeld geheugen inschakelen door een toepassingsinstelling met de naam FUNCTIONS_WORKER_SHARED_MEMORY_DATA_TRANSFER_ENABLED toe te voegen met een waarde van 1. Als gedeeld geheugen is ingeschakeld, kunt u vervolgens de DOCKER_SHM_SIZE-instelling gebruiken om het gedeelde geheugen in te stellen op iets als 268435456, wat gelijk is aan 256 MB.

U kunt bijvoorbeeld gedeeld geheugen inschakelen om knelpunten te verminderen wanneer u Blob Storage-bindingen gebruikt om nettoladingen van meer dan 1 MB over te dragen.

Deze functionaliteit is alleen beschikbaar voor functie-apps die worden uitgevoerd in Premium- en Dedicated-abonnementen (Azure-app Service). Zie Gedeeld geheugen voor meer informatie.

Bekende problemen en veelgestelde vragen

Hier volgen twee handleidingen voor probleemoplossing voor veelvoorkomende problemen:

Hier volgen twee handleidingen voor probleemoplossing voor bekende problemen met het v2-programmeermodel:

Alle bekende problemen en functieaanvragen worden bijgehouden in een GitHub-lijst met problemen. Als u een probleem ondervindt en het probleem niet kunt vinden in GitHub, opent u een nieuw probleem en geeft u een gedetailleerde beschrijving van het probleem op.

Volgende stappen

Voor meer informatie raadpleegt u de volgende bronnen:

Hebt u problemen met het gebruik van Python? Vertel ons wat er aan de hand is.