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 deze onderwerpen:
- Visual Studio Code: Uw eerste Python-app maken met Visual Studio Code.
- Terminal of opdrachtprompt: Maak uw eerste Python-app vanaf de opdrachtprompt met behulp van Azure Functions Core Tools.
- Voorbeelden: Bekijk enkele bestaande Python-apps in de learn-voorbeeldenbrowser.
- Visual Studio Code: Uw eerste Python-app maken met Visual Studio Code.
- Terminal of opdrachtprompt: Maak uw eerste Python-app vanaf de opdrachtprompt met behulp van Azure Functions Core Tools.
- Voorbeelden: Bekijk enkele bestaande Python-apps in de learn-voorbeeldenbrowser.
Ontwikkelingsopties
Beide Python Functions-programmeermodellen ondersteunen lokale ontwikkeling in een van de volgende omgevingen:
Python v2-programmeermodel:
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).
Als u verbinding wilt maken met Azure Cosmos DB, maakt u eerst een account, database en container. Vervolgens kunt u uw functiecode verbinden met Azure 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 asynchrone 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-durable
Blueprint
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. Verbindingsreeksen of geheimen voor trigger- en invoerbronnen worden toegewezen aan waarden in het local.settings.json-bestand wanneer ze lokaal worden uitgevoerd en worden 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
. Een vermelding wordt 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. Verbindingsreeksen of geheimen voor trigger- en invoerbronnen worden toegewezen aan waarden in het local.settings.json-bestand wanneer ze lokaal worden uitgevoerd en worden 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>"
}
}
# 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
. Een vermelding wordt 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.
SDK-typebindingen (preview)
Voor geselecteerde triggers en bindingen kunt u werken met gegevenstypen die zijn geïmplementeerd door de onderliggende Azure SDK's en frameworks. Met deze SDK-typebindingen kunt u bindingsgegevens gebruiken alsof u de onderliggende service-SDK gebruikt.
Belangrijk
Ondersteuning voor SDK-typebindingen vereist het Python v2-programmeermodel.
Functions ondersteunt Python SDK-typebindingen voor Azure Blob Storage, waarmee u met blobgegevens kunt werken met behulp van het onderliggende BlobClient
type.
Belangrijk
Ondersteuning voor SDK-typebindingen voor Python is momenteel beschikbaar als preview-versie:
- U moet het Python v2-programmeermodel gebruiken.
- Op dit moment worden alleen synchrone SDK-typen ondersteund.
Vereisten
- Versie 4.34 van Azure Functions Runtime of een nieuwere versie.
- Python-versie 3.9 of een nieuwere ondersteunde versie.
SDK-typebindingen inschakelen voor de Blob Storage-extensie
Voeg het
azurefunctions-extensions-bindings-blob
extensiepakket toe aan het bestand in hetrequirements.txt
project, dat ten minste de volgende pakketten moet bevatten:azure-functions azurefunctions-extensions-bindings-blob
Voeg deze code toe aan het bestand in het
function_app.py
project, waarmee de SDK-typebindingen worden geïmporteerd:import azurefunctions.extensions.bindings.blob as blob
Voorbeelden van SDK-typebindingen
In dit voorbeeld ziet u hoe u de BlobClient
trigger van zowel een Blob Storage-trigger (blob_trigger
) als van de invoerbinding op een HTTP-trigger (blob_input
):
import logging
import azure.functions as func
import azurefunctions.extensions.bindings.blob as blob
app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)
@app.blob_trigger(
arg_name="client", path="PATH/TO/BLOB", connection="AzureWebJobsStorage"
)
def blob_trigger(client: blob.BlobClient):
logging.info(
f"Python blob trigger function processed blob \n"
f"Properties: {client.get_blob_properties()}\n"
f"Blob content head: {client.download_blob().read(size=1)}"
)
@app.route(route="file")
@app.blob_input(
arg_name="client", path="PATH/TO/BLOB", connection="AzureWebJobsStorage"
)
def blob_input(req: func.HttpRequest, client: blob.BlobClient):
logging.info(
f"Python blob input function processed blob \n"
f"Properties: {client.get_blob_properties()}\n"
f"Blob content head: {client.download_blob().read(size=1)}"
)
return "ok"
U kunt andere voorbeelden van SDK-typebindingen voor Blob Storage bekijken in de opslagplaats voor Python-extensies:
HTTP-streams (preview)
Met HTTP-streams kunt u gegevens van uw HTTP-eindpunten accepteren en retourneren met behulp van FastAPI-aanvraag- en antwoord-API's die zijn ingeschakeld in uw functies. Met deze API's kan de host grote gegevens in HTTP-berichten verwerken als segmenten in plaats van een volledig bericht in het geheugen te lezen.
Met deze functie kunt u grote gegevensstromen, OpenAI-integraties verwerken, dynamische inhoud leveren en andere HTTP-kernscenario's ondersteunen waarvoor realtime interacties via HTTP zijn vereist. U kunt ook FastAPI-antwoordtypen gebruiken met HTTP-streams. Zonder HTTP-streams wordt de grootte van uw HTTP-aanvragen en -antwoorden beperkt door geheugenbeperkingen die kunnen worden aangetroffen bij het verwerken van volledige nettoladingen van berichten in het geheugen.
Belangrijk
Ondersteuning voor HTTP-streams vereist het Python v2-programmeermodel.
Belangrijk
Ondersteuning voor HTTP-streams voor Python is momenteel in preview en vereist dat u het Python v2-programmeermodel gebruikt.
Vereisten
- Azure Functions-runtimeversie 4.34.1 of een nieuwere versie.
- Python versie 3.8 of een nieuwere ondersteunde versie.
HTTP-streams inschakelen
HTTP-streams zijn standaard uitgeschakeld. U moet deze functie inschakelen in uw toepassingsinstellingen en ook uw code bijwerken voor het gebruik van het FastAPI-pakket. Houd er rekening mee dat bij het inschakelen van HTTP-streams de functie-app standaard GEBRUIKMAAKT van HTTP-streaming en dat de oorspronkelijke HTTP-functionaliteit niet werkt.
Voeg het
azurefunctions-extensions-http-fastapi
extensiepakket toe aan het bestand in hetrequirements.txt
project, dat ten minste de volgende pakketten moet bevatten:azure-functions azurefunctions-extensions-http-fastapi
Voeg deze code toe aan het
function_app.py
bestand in het project, waarmee de FastAPI-extensie wordt geïmporteerd:from azurefunctions.extensions.http.fastapi import Request, StreamingResponse
Wanneer u implementeert in Azure, voegt u de volgende toepassingsinstelling toe in uw functie-app:
"PYTHON_ENABLE_INIT_INDEXING": "1"
Als u implementeert in Linux-verbruik, voegt u ook
"PYTHON_ISOLATE_WORKER_DEPENDENCIES": "1"
Wanneer u lokaal werkt, moet u ook dezelfde instellingen toevoegen aan het
local.settings.json
projectbestand.
Voorbeelden van HTTP-streams
Nadat u de functie HTTP-streaming hebt ingeschakeld, kunt u functies maken die gegevens streamen via HTTP.
Dit voorbeeld is een door HTTP geactiveerde functie waarmee HTTP-antwoordgegevens worden gestreamd. U kunt deze mogelijkheden gebruiken om scenario's te ondersteunen, zoals het verzenden van gebeurtenisgegevens via een pijplijn voor realtimevisualisatie of het detecteren van afwijkingen in grote gegevenssets en het bieden van directe meldingen.
import time
import azure.functions as func
from azurefunctions.extensions.http.fastapi import Request, StreamingResponse
app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)
def generate_sensor_data():
"""Generate real-time sensor data."""
for i in range(10):
# Simulate temperature and humidity readings
temperature = 20 + i
humidity = 50 + i
yield f"data: {{'temperature': {temperature}, 'humidity': {humidity}}}\n\n"
time.sleep(1)
@app.route(route="stream", methods=[func.HttpMethod.GET])
async def stream_sensor_data(req: Request) -> StreamingResponse:
"""Endpoint to stream real-time sensor data."""
return StreamingResponse(generate_sensor_data(), media_type="text/event-stream")
Dit voorbeeld is een door HTTP geactiveerde functie die in realtime streaminggegevens van een client ontvangt en verwerkt. Het demonstreert mogelijkheden voor het uploaden van streaming die nuttig kunnen zijn voor scenario's zoals het verwerken van continue gegevensstromen en het verwerken van gebeurtenisgegevens van IoT-apparaten.
import azure.functions as func
from azurefunctions.extensions.http.fastapi import JSONResponse, Request
app = func.FunctionApp(http_auth_level=func.AuthLevel.ANONYMOUS)
@app.route(route="streaming_upload", methods=[func.HttpMethod.POST])
async def streaming_upload(req: Request) -> JSONResponse:
"""Handle streaming upload requests."""
# Process each chunk of data as it arrives
async for chunk in req.stream():
process_data_chunk(chunk)
# Once all data is received, return a JSON response indicating successful processing
return JSONResponse({"status": "Data uploaded and processed successfully"})
def process_data_chunk(chunk: bytes):
"""Process each data chunk."""
# Add custom processing logic here
pass
HTTP-streams aanroepen
U moet een HTTP-clientbibliotheek gebruiken om streaming-aanroepen naar fastAPI-eindpunten van een functie uit te voeren. Het clienthulpprogramma of de browser die u gebruikt, biedt mogelijk geen systeemeigen ondersteuning voor streaming of kan alleen het eerste deel van de gegevens retourneren.
U kunt een clientscript als dit gebruiken om streaminggegevens naar een HTTP-eindpunt te verzenden:
import httpx # Be sure to add 'httpx' to 'requirements.txt'
import asyncio
async def stream_generator(file_path):
chunk_size = 2 * 1024 # Define your own chunk size
with open(file_path, 'rb') as file:
while chunk := file.read(chunk_size):
yield chunk
print(f"Sent chunk: {len(chunk)} bytes")
async def stream_to_server(url, file_path):
timeout = httpx.Timeout(60.0, connect=60.0)
async with httpx.AsyncClient(timeout=timeout) as client:
response = await client.post(url, content=stream_generator(file_path))
return response
async def stream_response(response):
if response.status_code == 200:
async for chunk in response.aiter_raw():
print(f"Received chunk: {len(chunk)} bytes")
else:
print(f"Error: {response}")
async def main():
print('helloworld')
# Customize your streaming endpoint served from core tool in variable 'url' if different.
url = 'http://localhost:7071/api/streaming_upload'
file_path = r'<file path>'
response = await stream_to_server(url, file_path)
print(response)
if __name__ == "__main__":
asyncio.run(main())
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 waarin een lokaal invocation_id
kenmerk thread_local_storage
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 routePrefix
op 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:
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 routePrefix
op 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.
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_URL
maken. 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 install
voor 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 uw .venv
virtuele Python-omgevingsmap, 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:
- Standaardbibliotheek voor Python 3.8
- Standaardbibliotheek voor Python 3.9
- Standaardbibliotheek voor Python 3.10
- Standaardbibliotheek voor Python 3.11
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.
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:
- Voeg het extensiepakket toe aan het requirements.txt-bestand voor uw project.
- Installeer de bibliotheek in uw app.
- Voeg de volgende toepassingsinstellingen toe:
- Lokaal: Voer
"PYTHON_ENABLE_WORKER_EXTENSIONS": "1"
in deValues
sectie van het local.settings.json-bestand in. - Azure: Voer
PYTHON_ENABLE_WORKER_EXTENSIONS=1
uw app-instellingen in.
- Lokaal: Voer
- Importeer de extensiemodule in uw functietrigger.
- 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:
- Kan bestand of assembly niet laden
- Kan de Azure Storage-verbinding met de naam Storage niet oplossen
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:
- Api-documentatie voor Azure Functions-pakketten
- Aanbevolen procedures voor Azure Functions
- Azure Functions-triggers en -bindingen
- Blob Storage-bindingen
- HTTP- en webhook-bindingen
- Queue Storage-bindingen
- Timertriggers
Hebt u problemen met het gebruik van Python? Vertel ons wat er aan de hand is.