Sdílet prostřednictvím


Azure Functions – Příručka pro vývojáře v Pythonu

Tento průvodce představuje úvod do vývoje azure Functions pomocí Pythonu. Článek předpokládá, že jste už přečetli příručku pro vývojáře Azure Functions.

Důležité

Tento článek podporuje programovací model v1 i v2 pro Python ve službě Azure Functions. Model Pythonu v1 používá k definování funkcí soubor functions.json a nový model v2 umožňuje místo toho použít přístup založený na dekorátoru. Výsledkem tohoto nového přístupu je jednodušší struktura souborů, která je zaměřená na kód. V horní části článku zvolte selektor v2, abyste se dozvěděli o tomto novém programovacím modelu.

Jako vývojář Pythonu vás můžou zajímat také tato témata:

  • Visual Studio Code: Vytvořte svou první aplikaci v Pythonu pomocí editoru Visual Studio Code.
  • Terminál nebo příkazový řádek: Vytvořte svou první aplikaci v Pythonu z příkazového řádku pomocí nástrojů Azure Functions Core Tools.
  • Ukázky: Projděte si některé existující aplikace Pythonu v prohlížeči ukázek Learn.
  • Visual Studio Code: Vytvořte svou první aplikaci v Pythonu pomocí editoru Visual Studio Code.
  • Terminál nebo příkazový řádek: Vytvořte svou první aplikaci v Pythonu z příkazového řádku pomocí nástrojů Azure Functions Core Tools.
  • Ukázky: Projděte si některé existující aplikace Pythonu v prohlížeči ukázek Learn.

Možnosti vývoje

Oba programovací modely Python Functions podporují místní vývoj v jednom z následujících prostředí:

Programovací model Pythonu v2:

Programovací model Pythonu v1:

Funkce Pythonu v1 můžete vytvořit také na webu Azure Portal.

Tip

I když můžete vyvíjet funkce Azure založené na Pythonu místně ve Windows, Python se podporuje jenom v plánu hostování založeném na Linuxu, když běží v Azure. Další informace najdete v seznamu podporovaných kombinací operačního systému nebo modulu runtime.

Programovací model

Služba Azure Functions očekává, že ve skriptu Pythonu bude funkce bezstavová metoda, která zpracuje vstup a vytvoří výstup. Modul runtime ve výchozím nastavení očekává, že se metoda implementuje jako globální metoda volaná main() v souboru __init__.py . Můžete také zadat alternativní vstupní bod.

Data se váže na funkci z triggerů a vazeb prostřednictvím atributů metody, které používají name vlastnost definovanou v souboru function.json . Například následující soubor function.json popisuje jednoduchou funkci aktivovanou požadavkem HTTP s názvem req:

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

Na základě této definice může soubor __init__.py, který obsahuje kód funkce, vypadat jako v následujícím příkladu:

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

Pomocí poznámek k typu Pythonu můžete také explicitně deklarovat typy atributů a návratový typ funkce. To vám pomůže používat IntelliSense a funkce automatického dokončování, které poskytuje mnoho editorů kódu Pythonu.

import azure.functions

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

Pomocí poznámek Pythonu, které jsou součástí balíčku azure.functions.* k vytvoření vazby vstupu a výstupů k vašim metodám.

Služba Azure Functions očekává, že ve skriptu Pythonu bude funkce bezstavová metoda, která zpracuje vstup a vytvoří výstup. Modul runtime ve výchozím nastavení očekává, že se metoda implementuje jako globální metoda v souboru function_app.py .

Triggery a vazby lze deklarovat a používat ve funkci v přístupu založeném na dekorátoru. Jsou definované ve stejném souboru function_app.py jako funkce. Například následující soubor function_app.py představuje trigger funkce požadavkem HTTP.

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

Pomocí poznámek k typu Pythonu můžete také explicitně deklarovat typy atributů a návratový typ funkce. To vám pomůže používat funkce IntelliSense a automatické dokončování, které poskytuje mnoho editorů kódu Pythonu.

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}!"

Informace o známých omezeních modelu v2 a jejich alternativních řešeních najdete v tématu Řešení chyb Pythonu ve službě Azure Functions.

Alternativní vstupní bod

Výchozí chování funkce můžete změnit tak, že volitelně zadáte scriptFile vlastnosti v entryPoint souboru function.json . Například následující function.json modulu runtime říká, aby jako vstupní bod vaší funkce Azure použil customentry() metodu v souboru main.py .

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

Vstupní bod je pouze v souboru function_app.py . Na funkce v projektu však můžete odkazovat v function_app.py pomocí podrobných plánů nebo importem.

Struktura složek

Doporučená struktura složek pro projekt funkcí Pythonu vypadá jako v následujícím příkladu:

 <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

Hlavní složka projektu, <project_root>, může obsahovat následující soubory:

  • local.settings.json: Používá se k ukládání nastavení aplikací a připojovací řetězec při místním spuštění. Tento soubor se nepublikuje do Azure. Další informace najdete v souboru local.settings.file.
  • requirements.txt: Obsahuje seznam balíčků Pythonu, které systém nainstaluje při publikování do Azure.
  • host.json: Obsahuje možnosti konfigurace, které ovlivňují všechny funkce v instanci aplikace funkcí. Tento soubor se publikuje do Azure. Při místním spuštění nejsou podporované všechny možnosti. Další informace najdete v tématu host.json.
  • .vscode/: (volitelné) Obsahuje uloženou konfiguraci editoru Visual Studio Code. Další informace najdete v nastavení editoru Visual Studio Code.
  • .venv/: (volitelné) Obsahuje virtuální prostředí Pythonu používané místním vývojem.
  • Dockerfile: (Volitelné) Používá se při publikování projektu ve vlastním kontejneru.
  • tests/: (Volitelné) Obsahuje testovací případy vaší aplikace funkcí.
  • .funcignore: (Volitelné) Deklaruje soubory, které by se neměly publikovat do Azure. Tento soubor obvykle obsahuje soubor .vscode/ pro ignorování nastavení editoru , .venv/ pro ignorování místního virtuálního prostředí Pythonu, testů a ignorování testovacích případů a local.settings.json , aby se zabránilo publikování místního nastavení aplikace.

Každá funkce má vlastní soubor kódu a konfigurační soubor vazby function.json.

Doporučená struktura složek pro projekt funkcí Pythonu vypadá jako v následujícím příkladu:

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

Hlavní složka projektu, <project_root>, může obsahovat následující soubory:

  • .venv/: (Volitelné) Obsahuje virtuální prostředí Pythonu, které používá místní vývoj.
  • .vscode/: (volitelné) Obsahuje uloženou konfiguraci editoru Visual Studio Code. Další informace najdete v nastavení editoru Visual Studio Code.
  • function_app.py: Výchozí umístění pro všechny funkce a související triggery a vazby.
  • additional_functions.py: (Volitelné) Všechny ostatní soubory Pythonu, které obsahují funkce (obvykle pro logické seskupení), které jsou odkazovány v function_app.py prostřednictvím podrobných plánů.
  • tests/: (Volitelné) Obsahuje testovací případy vaší aplikace funkcí.
  • .funcignore: (Volitelné) Deklaruje soubory, které by se neměly publikovat do Azure. Tento soubor obvykle obsahuje soubor .vscode/ pro ignorování nastavení editoru , .venv/ pro ignorování místního virtuálního prostředí Pythonu, testů/ ignorování testovacích případů a local.settings.json , aby se zabránilo publikování nastavení místní aplikace.
  • host.json: Obsahuje možnosti konfigurace, které ovlivňují všechny funkce v instanci aplikace funkcí. Tento soubor se publikuje do Azure. Při místním spuštění nejsou podporované všechny možnosti. Další informace najdete v tématu host.json.
  • local.settings.json: Slouží k ukládání nastavení aplikací a připojovací řetězec při místním spuštění. Tento soubor se nepublikuje do Azure. Další informace najdete v souboru local.settings.file.
  • requirements.txt: Obsahuje seznam balíčků Pythonu, které systém nainstaluje při publikování do Azure.
  • Dockerfile: (Volitelné) Používá se při publikování projektu ve vlastním kontejneru.

Když projekt nasadíte do aplikace funkcí v Azure, celý obsah hlavní složky projektu project_root <>by měl být součástí balíčku, ale ne do samotné složky, což znamená, že host.json by měl být v kořenovém adresáři balíčku. Doporučujeme udržovat testy ve složce spolu s dalšími funkcemi (v tomto příkladu testy/). Další informace najdete v tématu Testování částí.

Připojit k databázi

Azure Functions se dobře integruje se službou Azure Cosmos DB pro mnoho případů použití, včetně IoT, elektronického obchodování, hraní atd.

Například pro event sourcing jsou dvě služby integrované do architektur řízených událostmi pomocí funkcí kanálu změn ve službě Azure Cosmos DB. Kanál změn poskytuje podřízené mikroslužby schopnost spolehlivě a přírůstkově číst vkládání a aktualizace (například události objednávek). Tuto funkci lze použít k zajištění trvalého úložiště událostí jako zprostředkovatele zpráv pro události změny stavu a pracovní postup zpracování pořadí jednotek mezi mnoha mikroslužbami (které je možné implementovat jako bezserverové funkce Azure Functions).

Referenční architektura kanálu řazení ve službě Azure Cosmos DB

Pokud se chcete připojit ke službě Azure Cosmos DB, nejprve vytvořte účet, databázi a kontejner. Pak můžete kód funkce připojit ke službě Azure Cosmos DB pomocí triggeru a vazeb, jako je tento příklad.

Pokud chcete implementovat složitější logiku aplikace, můžete také použít knihovnu Pythonu pro Cosmos DB. Asynchronní implementace vstupně-výstupních operací vypadá takto:

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

Programovací model Pythonu v2 představuje koncept podrobných plánů. Podrobný plán je nová třída, která se vytvoří instance pro registraci funkcí mimo základní aplikaci funkcí. Funkce zaregistrované v instancích podrobného plánu nejsou indexovány přímo modulem runtime funkce. Aby se tyto funkce podrobného plánu indexovaly, musí aplikace funkcí zaregistrovat funkce z instancí podrobného plánu.

Použití podrobných plánů poskytuje následující výhody:

  • Umožňuje rozdělit aplikaci funkcí na modulární komponenty, které umožňují definovat funkce ve více souborech Pythonu a rozdělit je na jednotlivé soubory.
  • Poskytuje rozšiřitelná rozhraní veřejných aplikací funkcí pro sestavování a opakované použití vlastních rozhraní API.

Následující příklad ukazuje, jak používat podrobné plány:

Nejprve je v souboru http_blueprint.py definována funkce aktivovaná protokolem HTTP a přidána do objektu podrobného plánu.

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 
        ) 

Dále se v souboru function_app.py naimportuje objekt podrobného plánu a jeho funkce se zaregistrují do aplikace funkcí.

import azure.functions as func 
from http_blueprint import bp

app = func.FunctionApp() 

app.register_functions(bp) 

Poznámka:

Durable Functions také podporuje podrobné plány. Pokud chcete vytvářet podrobné plány pro aplikace Durable Functions, zaregistrujte orchestraci, aktivitu a triggery entit a vazby klientů pomocí azure-functions-durable Blueprint třídy, jak je znázorněno zde. Výsledný podrobný plán je pak možné zaregistrovat jako normální. Příklad najdete v naší ukázce .

Chování importu

Moduly v kódu funkce můžete importovat pomocí absolutních i relativních odkazů. Na základě dříve popsané struktury složek fungují následující importy z souboru <funkce 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)

Poznámka:

Pokud používáte absolutní syntaxi importu, musí shared_code/ složka obsahovat soubor __init__.py , který ho označí jako balíček Pythonu.

Následující __app__ import a nad rámec relativního importu nejvyšší úrovně jsou zastaralé, protože nejsou podporovány kontrolou statického typu a nepodporují se testovacími architekturami Pythonu:

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)

Triggery a vstupy

Vstupy jsou rozdělené do dvou kategorií ve službě Azure Functions: vstup triggeru a další vstup. I když se v souboru function.json liší, jejich použití je v kódu Pythonu stejné. Připojovací řetězce nebo tajné kódy pro trigger a vstupní zdroje se mapují na hodnoty v souboru local.settings.json , když jsou spuštěné místně, a při spuštění v Azure se mapují na nastavení aplikace.

Například následující kód ukazuje rozdíl mezi těmito dvěma vstupy:

// 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()}')

Při vyvolání funkce se požadavek HTTP předá funkci jako req. Položka se načte z účtu služby Azure Blob Storage na základě ID v adrese URL trasy a zpřístupní se jako obj v těle funkce. Tady je zadaný účet úložiště připojovací řetězec, který se nachází v CONNECTION_STRING nastavení aplikace.

Vstupy jsou rozdělené do dvou kategorií ve službě Azure Functions: vstup triggeru a další vstup. I když jsou definované pomocí různých dekorátorů, jejich použití je podobné v kódu Pythonu. Připojovací řetězce nebo tajné kódy pro trigger a vstupní zdroje se mapují na hodnoty v souboru local.settings.json , když jsou spuštěné místně, a při spuštění v Azure se mapují na nastavení aplikace.

Následující kód například ukazuje, jak definovat vstupní vazbu služby Blob Storage:

// 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()}')

Při vyvolání funkce se požadavek HTTP předá funkci jako req. Položka se načte z účtu služby Azure Blob Storage na základě ID v adrese URL trasy a zpřístupní se jako obj v těle funkce. Tady je zadaný účet úložiště připojovací řetězec, který se nachází v STORAGE_CONNECTION_STRING nastavení aplikace.

Pro operace s vazbami náročnými na data můžete chtít použít samostatný účet úložiště. Další informace najdete v doprovodných materiálech k účtu úložiště.

Vazby typu sady SDK (Preview)

U vybraných triggerů a vazeb můžete pracovat s datovými typy implementovanými podkladovými sadami Azure SDK a architekturami. Tyto vazby typu sady SDK umožňují interakci s daty , jako kdybyste používali podkladovou sadu SDK služby.

Důležité

Podpora vazeb typu sady SDK vyžaduje programovací model Pythonu v2.

Functions podporuje vazby typů sady Python SDK pro úložiště objektů blob v Azure, které umožňují pracovat s daty objektů blob pomocí základního BlobClient typu.

Důležité

Podpora vazeb typu sady SDK pro Python je aktuálně ve verzi Preview:

  • Musíte použít programovací model Pythonu v2.
  • V současné době se podporují pouze synchronní typy sad SDK.

Požadavky

Povolení vazeb typu sady SDK pro rozšíření úložiště objektů blob

  1. azurefunctions-extensions-bindings-blob Přidejte balíček přípony requirements.txt do souboru v projektu, který by měl obsahovat alespoň tyto balíčky:

    azure-functions
    azurefunctions-extensions-bindings-blob
    
  2. Přidejte tento kód do function_app.py souboru v projektu, který importuje vazby typu sady SDK:

    import azurefunctions.extensions.bindings.blob as blob
    

Příklady vazeb typu sady SDK

Tento příklad ukazuje, jak získat z triggeru BlobClient úložiště objektů blob (blob_trigger) i ze vstupní vazby triggeru HTTP (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"

V úložišti rozšíření Pythonu můžete zobrazit další ukázky vazeb typů sady SDK pro úložiště objektů blob:

Streamy HTTP (Preview)

Streamy HTTP umožňují přijímat a vracet data z koncových bodů HTTP pomocí rozhraní API požadavků FastAPI a odpovědí povolených ve vašich funkcích. Tato rozhraní API umožňují hostiteli zpracovávat velká data ve zprávách HTTP jako bloky dat místo čtení celé zprávy do paměti.

Tato funkce umožňuje zpracovávat velké datové proudy, integrace OpenAI, dodávat dynamický obsah a podporovat další základní scénáře HTTP vyžadující interakce v reálném čase přes HTTP. U streamů HTTP můžete také použít typy odpovědí FastAPI. Bez datových proudů HTTP jsou velikost požadavků a odpovědí HTTP omezena omezeními paměti, ke kterým může dojít při zpracování celých datových částí zpráv v paměti.

Důležité

Podpora datových proudů HTTP vyžaduje programovací model Pythonu v2.

Důležité

Podpora datových proudů HTTP pro Python je aktuálně ve verzi Preview a vyžaduje použití programovacího modelu Pythonu v2.

Požadavky

Povolení streamů HTTP

Streamy HTTP jsou ve výchozím nastavení zakázané. Tuto funkci musíte povolit v nastavení aplikace a také aktualizovat kód tak, aby používal balíček FastAPI. Všimněte si, že když povolíte streamy HTTP, aplikace funkcí ve výchozím nastavení použije streamování HTTP a původní funkce HTTP nebudou fungovat.

  1. azurefunctions-extensions-http-fastapi Přidejte balíček přípony requirements.txt do souboru v projektu, který by měl obsahovat alespoň tyto balíčky:

    azure-functions
    azurefunctions-extensions-http-fastapi
    
  2. Přidejte tento kód do function_app.py souboru v projektu, který importuje příponu FastAPI:

    from azurefunctions.extensions.http.fastapi import Request, StreamingResponse
    
  3. Když nasadíte do Azure, přidejte do aplikace funkcí následující nastavení aplikace:

    "PYTHON_ENABLE_INIT_INDEXING": "1"

    Pokud nasazujete do linuxové spotřeby, přidejte také

    "PYTHON_ISOLATE_WORKER_DEPENDENCIES": "1"

    Při místním spuštění je také potřeba přidat tato stejná nastavení do local.settings.json souboru projektu.

Příklady streamů HTTP

Po povolení funkce streamování HTTP můžete vytvořit funkce, které streamuje data přes PROTOKOL HTTP.

Tento příklad je funkce aktivovaná protokolem HTTP, která streamuje data odpovědi HTTP. Tyto funkce můžete použít k podpoře scénářů, jako je odesílání dat událostí prostřednictvím kanálu pro vizualizaci v reálném čase nebo zjišťování anomálií ve velkých sadách dat a poskytování rychlých oznámení.

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

Tento příklad je funkce aktivovaná protokolem HTTP, která přijímá a zpracovává streamovaná data z klienta v reálném čase. Ukazuje možnosti nahrávání streamování, které můžou být užitečné pro scénáře, jako je zpracování nepřetržitých datových proudů a zpracování dat událostí ze zařízení IoT.

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

Volání datových proudů HTTP

Ke streamování volání koncových bodů FastAPI funkce musíte použít klientskou knihovnu HTTP. Klientský nástroj nebo prohlížeč, který používáte, nemusí nativně podporovat streamování nebo může vrátit pouze první blok dat.

K odesílání streamovaných dat do koncového bodu HTTP můžete použít podobný klientský skript:

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

Výstupy

Výstup se dá vyjádřit jak ve návratové hodnotě, tak ve výstupních parametrech. Pokud existuje jenom jeden výstup, doporučujeme použít návratovou hodnotu. Pro více výstupů musíte použít výstupní parametry.

Chcete-li použít návratovou hodnotu funkce jako hodnotu výstupní vazby, name vlastnost vazby by měla být nastavena na $return v souboru function.json .

Chcete-li vytvořit více výstupů, použijte metodu set() poskytovanou azure.functions.Out rozhraním k přiřazení hodnoty k vazbě. Například následující funkce může odeslat zprávu do fronty a také vrátit odpověď HTTP.

{
  "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

Výstup se dá vyjádřit jak ve návratové hodnotě, tak ve výstupních parametrech. Pokud existuje jenom jeden výstup, doporučujeme použít návratovou hodnotu. Pro více výstupů budete muset použít výstupní parametry.

Chcete-li vytvořit více výstupů, použijte metodu set() poskytovanou azure.functions.Out rozhraním k přiřazení hodnoty k vazbě. Například následující funkce může odeslat zprávu do fronty a také vrátit odpověď HTTP.

# 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

Protokolování

Přístup k protokolovacímu modulu runtime Azure Functions je k dispozici prostřednictvím kořenové logging obslužné rutiny ve vaší aplikaci funkcí. Tento protokolovací modul je svázaný s Application Insights a umožňuje označit upozornění a chyby, ke kterým dochází během provádění funkce.

Následující příklad zaznamená informační zprávu při vyvolání funkce prostřednictvím triggeru HTTP.

import logging

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

K dispozici jsou další metody protokolování, které umožňují zapisovat do konzoly na různých úrovních trasování:

metoda Popis
critical(_message_) Zapíše zprávu s úrovní CRITICAL v kořenovém protokolovacím nástroje.
error(_message_) Zapíše zprávu s úrovní ERROR v kořenovém protokolovacím nástroje.
warning(_message_) Zapíše zprávu s upozorněním na úrovni v kořenovém protokolovacím nástroje.
info(_message_) Zapíše zprávu s informací o úrovni v kořenovém protokolovacím systému.
debug(_message_) Zapíše zprávu s úrovní DEBUG v kořenovém protokolovacím nástroji.

Další informace o protokolování najdete v tématu Monitorování azure Functions.

Protokolování z vytvořených vláken

Pokud chcete zobrazit protokoly pocházející z vytvořených vláken, zahrňte context do podpisu funkce argument. Tento argument obsahuje atribut thread_local_storage , který ukládá místní invocation_id. To lze nastavit na aktuální invocation_id funkci, aby se zajistilo, že se kontext změní.

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.')

Protokolování vlastní telemetrie

Modul runtime služby Functions ve výchozím nastavení shromažďuje protokoly a další telemetrická data generovaná vašimi funkcemi. Tato telemetrie končí jako trasování ve službě Application Insights. Telemetrie požadavků a závislostí pro určité služby Azure se ve výchozím nastavení shromažďují také triggery a vazby.

Pokud chcete shromažďovat vlastní telemetrii požadavků a vlastních závislostí mimo vazby, můžete použít rozšíření OpenCensus Python. Toto rozšíření odesílá vlastní telemetrická data do vaší instance Application Insights. Seznam podporovaných rozšíření najdete v úložišti OpenCensus.

Poznámka:

Pokud chcete použít rozšíření OpenCensus Python, musíte ve své aplikaci funkcí povolit rozšíření pracovních procesů Pythonu nastavením PYTHON_ENABLE_WORKER_EXTENSIONS na 1. Musíte také přepnout na používání služby Application Insights připojovací řetězec tak, že do nastavení aplikace přidáte APPLICATIONINSIGHTS_CONNECTION_STRING nastavení, pokud tam ještě není.

// 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,
    })

Trigger HTTP

Trigger HTTP je definován v souboru function.json . Vazba name musí odpovídat pojmenovaného parametru ve funkci. V předchozích příkladech se používá název req vazby. Tento parametr je objekt HttpRequest a je vrácen objekt HttpResponse .

Z objektu HttpRequest můžete získat hlavičky požadavku, parametry dotazu, parametry trasy a text zprávy.

Následující příklad je ze šablony triggeru HTTP pro 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
        )

V této funkci získáte hodnotu parametru name dotazu z params parametru HttpRequest objektu. Text zprávy kódovaný ve formátu JSON si můžete přečíst pomocí get_json metody.

Podobně můžete nastavit status_code a headers pro zprávu odpovědi ve vrácený objekt HttpResponse .

Trigger HTTP je definován jako metoda, která přebírá pojmenovaný binding parametr, což je HttpRequest objekt a vrací HttpResponse objekt. Dekorátor použijete function_name na metodu pro definování názvu funkce, zatímco koncový bod HTTP je nastaven použitím dekorátoru route .

Tento příklad pochází ze šablony triggeru HTTP pro programovací model Pythonu v2, kde je reqnázev parametru vazby . Jedná se o ukázkový kód, který je k dispozici při vytváření funkce pomocí nástrojů Azure Functions Core Tools nebo editoru 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
        )

Z objektu HttpRequest můžete získat hlavičky požadavku, parametry dotazu, parametry trasy a text zprávy. V této funkci získáte hodnotu parametru name dotazu z params parametru HttpRequest objektu. Text zprávy kódovaný ve formátu JSON si můžete přečíst pomocí get_json metody.

Podobně můžete nastavit status_code a headers pro zprávu odpovědi ve vrácený objekt HttpResponse .

Pokud chcete předat název v tomto příkladu, vložte adresu URL, která je zadaná při spuštění funkce, a pak ji připojte pomocí "?name={name}".

Webové architektury

S funkcemi Pythonu aktivovanými protokolem HTTP můžete použít rozhraní kompatibilní s rozhraním WSGI (Web Server Gateway Interface) kompatibilní s rozhraním WSGI (Web Server Gateway Interface). Tato část ukazuje, jak upravit funkce tak, aby podporovaly tyto architektury.

Nejprve musí být soubor function.json aktualizován tak, aby zahrnoval route trigger HTTP, jak je znázorněno v následujícím příkladu:

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

Soubor host.json musí být také aktualizován tak, aby zahrnoval PROTOKOL HTTP routePrefix, jak je znázorněno v následujícím příkladu:

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

Aktualizujte soubor kódu Pythonu init.py v závislosti na rozhraní používaném vaší architekturou. Následující příklad ukazuje přístup obslužné rutiny ASGI nebo metodu obálky WSGI pro 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)

S funkcemi Pythonu aktivovanými protokolem HTTP můžete použít rozhraní kompatibilní s asynchronním serverovým rozhraním (ASGI) a rozhraním WSGI (Web Server Gateway Interface). Nejprve je nutné aktualizovat soubor host.json tak, aby zahrnoval PROTOKOL HTTP routePrefix, jak je znázorněno v následujícím příkladu:

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

Kód architektury vypadá jako v následujícím příkladu:

AsgiFunctionApp je třída aplikace funkcí nejvyšší úrovně pro vytváření funkcí ASGI HTTP.

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

Škálování a výkon

Osvědčené postupy škálování a výkonu pro aplikace funkcí Pythonu najdete v článku o škálování a výkonu Pythonu.

Kontext

Pokud chcete získat kontext vyvolání funkce při jeho spuštění, zahrňte context do podpisu argument.

Příklad:

import azure.functions


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

Třída Context má následující atributy řetězce:

Atribut Popis
function_directory Adresář, ve kterém je funkce spuštěná.
function_name Název funkce.
invocation_id ID vyvolání aktuální funkce.
thread_local_storage Místní úložiště podprocesu funkce. Obsahuje místní invocation_id prostředí pro protokolování z vytvořených vláken.
trace_context Kontext distribuovaného trasování. Další informace najdete na webu Trace Context.
retry_context Kontext pro opakování funkce. Další informace najdete na webu retry-policies.

Globální proměnné

Není zaručeno, že se stav vaší aplikace zachová pro budoucí spuštění. Modul runtime Azure Functions ale často používá stejný proces pro více spuštění stejné aplikace. Pokud chcete výsledky nákladného výpočtu uložit do mezipaměti, deklarujte ho jako globální proměnnou.

CACHED_DATA = None


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

    # ... use CACHED_DATA in code

Proměnné prostředí

V Azure Functions se nastavení aplikace, jako jsou připojovací řetězec služby, zobrazují jako proměnné prostředí při jejich spuštění. Existují dva hlavní způsoby přístupu k těmto nastavením v kódu.

metoda Popis
os.environ["myAppSetting"] Pokusí se získat nastavení aplikace podle názvu klíče a vyvolá chybu, když je neúspěšná.
os.getenv("myAppSetting") Pokusí se získat nastavení aplikace podle názvu klíče a vrátí None , když je neúspěšná.

Oba tyto způsoby vyžadují, abyste deklarovat import os.

Následující příklad používá os.environ["myAppSetting"] k získání nastavení aplikace s názvem myAppSettingklíč :

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}')

Pro místní vývoj se nastavení aplikace udržuje v souboru local.settings.json.

V Azure Functions se nastavení aplikace, jako jsou připojovací řetězec služby, zobrazují jako proměnné prostředí při jejich spuštění. Existují dva hlavní způsoby přístupu k těmto nastavením v kódu.

metoda Popis
os.environ["myAppSetting"] Pokusí se získat nastavení aplikace podle názvu klíče a vyvolá chybu, když je neúspěšná.
os.getenv("myAppSetting") Pokusí se získat nastavení aplikace podle názvu klíče a vrátí None , když je neúspěšná.

Oba tyto způsoby vyžadují, abyste deklarovat import os.

Následující příklad používá os.environ["myAppSetting"] k získání nastavení aplikace s názvem myAppSettingklíč :

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}')

Pro místní vývoj se nastavení aplikace udržuje v souboru local.settings.json.

Verze Pythonu

Azure Functions podporuje následující verze Pythonu:

Verze služby Functions Verze Pythonu*
4.x 3.11
3,10
3.9
3.8
3.7
3.x 3.9
3.8
3.7

* Oficiální distribuce Pythonu

Pokud chcete při vytváření aplikace funkcí v Azure požádat o konkrétní verzi Pythonu --runtime-version az functionapp create , použijte možnost příkazu. Verze modulu runtime Služby Functions je nastavena možností --functions-version . Verze Pythonu se nastavuje při vytváření aplikace funkcí a nedá se změnit pro aplikace spuštěné v plánu Consumption.

Modul runtime používá dostupnou verzi Pythonu při místním spuštění.

Změna verze Pythonu

Pokud chcete nastavit aplikaci funkcí Pythonu na konkrétní jazykovou verzi, musíte zadat jazyk a verzi jazyka v LinuxFxVersion poli v konfiguraci webu. Pokud chcete například změnit aplikaci Python tak, aby používala Python 3.8, nastavte linuxFxVersion na python|3.8.

Informace o tom, jak zobrazit a změnit nastavení webu, najdete v linuxFxVersion tématu Postup cílení na verze modulu runtime Azure Functions.

Další obecné informace najdete v zásadách podpory modulu runtime Azure Functions a podporovaných jazycích ve službě Azure Functions.

Správa balíčků

Při místním vývoji pomocí nástrojů Core Tools nebo editoru Visual Studio Code přidejte názvy a verze požadovaných balíčků do souboru requirements.txt a pak je nainstalujte pomocí pip.

Můžete například použít následující requirements.txt soubor a pip příkaz k instalaci requests balíčku z PyPI.

requests==2.19.1
pip install -r requirements.txt

Při spouštění funkcí v plánu služby App Service mají závislosti, které definujete v requirements.txt, přednost před integrovanými moduly Pythonu, například logging. Tato priorita může způsobit konflikty v případě, že integrované moduly mají v kódu stejné názvy jako adresáře. Při spuštění v plánu Consumption nebo v plánu Elastic Premium jsou konflikty méně pravděpodobné, protože vaše závislosti nejsou ve výchozím nastavení upřednostňované.

Pokud chcete zabránit problémům spuštěným v plánu služby App Service, neozvěte adresáře stejně jako žádné nativní moduly Pythonu a nezahrnujte nativní knihovny Pythonu do souboru requirements.txt projektu.

Publikování do Azure

Až budete připraveni publikovat, ujistěte se, že jsou všechny veřejně dostupné závislosti uvedené v souboru requirements.txt . Tento soubor můžete najít v kořenovém adresáři projektu.

Soubory a složky projektu, které jsou vyloučené z publikování, včetně složky virtuálního prostředí, najdete v kořenovém adresáři projektu.

Publikování projektu Pythonu do Azure podporuje tři akce sestavení: vzdálené sestavení, místní sestavení a sestavení s využitím vlastních závislostí.

Azure Pipelines můžete také použít k sestavení závislostí a publikování pomocí průběžného doručování (CD). Další informace najdete v tématu Průběžné doručování pomocí Azure Pipelines.

Vzdálené sestavení

Při použití vzdáleného sestavení se závislosti obnovené na serveru a nativní závislosti shodují s produkčním prostředím. Výsledkem je menší balíček pro nasazení, který se má nahrát. Při vývoji aplikací Pythonu ve Windows používejte vzdálené sestavení. Pokud má váš projekt vlastní závislosti, můžete použít vzdálené sestavení s další adresou URL indexu.

Závislosti se získávají vzdáleně na základě obsahu souboru requirements.txt . Vzdálené sestavení je doporučená metoda sestavení. Core Tools ve výchozím nastavení požádá o vzdálené sestavení, když k publikování projektu Pythonu do Azure použijete následující func azure functionapp publish příkaz.

func azure functionapp publish <APP_NAME>

Nezapomeňte nahradit <APP_NAME> názvem vaší aplikace funkcí v Azure.

Rozšíření Azure Functions pro Visual Studio Code také ve výchozím nastavení vyžaduje vzdálené sestavení.

Místní sestavení

Závislosti se získávají místně na základě obsahu souboru requirements.txt . Vzdálenému sestavení můžete zabránit tak, že pomocí následujícího func azure functionapp publish příkazu publikujete místní sestavení:

func azure functionapp publish <APP_NAME> --build local

Nezapomeňte nahradit <APP_NAME> názvem vaší aplikace funkcí v Azure.

Při použití --build local této možnosti se závislosti projektu čtou ze souboru requirements.txt a závislé balíčky se stáhnou a nainstalují místně. Soubory a závislosti projektu se nasazují z místního počítače do Azure. Výsledkem je nahrání většího balíčku nasazení do Azure. Pokud z nějakého důvodu nemůžete získat soubor requirements.txt pomocí nástrojů Core Tools, musíte pro publikování použít vlastní závislosti.

Při místním vývoji ve Windows nedoporučujeme používat místní buildy.

Vlastní závislosti

Pokud projekt obsahuje závislosti, které nejsou nalezeny v indexu balíčků Pythonu, existují dva způsoby sestavení projektu. První způsob, metoda sestavení , závisí na tom, jak sestavíte projekt.

Vzdálené sestavení s extra adresou URL indexu

Pokud jsou balíčky dostupné z přístupného vlastního indexu balíčků, použijte vzdálené sestavení. Před publikováním nezapomeňte vytvořit nastavení aplikace s názvem PIP_EXTRA_INDEX_URL. Hodnota tohoto nastavení je adresa URL vlastního indexu balíčku. Pomocí tohoto nastavení sdělíte vzdálenému sestavení, aby se spustilo pip install pomocí --extra-index-url této možnosti. Další informace najdete v dokumentaci k Pythonu.pip install

Základní ověřovací přihlašovací údaje můžete použít také s dalšími adresami URL indexu balíčků. Další informace najdete v dokumentaci k Základním ověřovacím přihlašovacím údajům v Pythonu.

Instalace místních balíčků

Pokud váš projekt používá balíčky, které nejsou veřejně dostupné pro naše nástroje, můžete je zpřístupnit vaší aplikaci tak, že je vložíte do adresáře __app__/.python_packages . Před publikováním nainstalujte závislosti místně spuštěním následujícího příkazu:

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

Pokud používáte vlastní závislosti, měli byste použít --no-build možnost publikování, protože jste už do složky projektu nainstalovali závislosti.

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

Nezapomeňte nahradit <APP_NAME> názvem vaší aplikace funkcí v Azure.

Testování částí

Funkce napsané v Pythonu je možné testovat stejně jako ostatní kódy Pythonu pomocí standardních testovacích architektur. U většiny vazeb je možné vytvořit napodobený vstupní objekt vytvořením instance příslušné třídy z azure.functions balíčku. azure.functions Vzhledem k tomu, že balíček není okamžitě dostupný, nezapomeňte ho nainstalovat přes soubor requirements.txt, jak je popsáno v části správa balíčků výše.

V případě my_second_function jako příkladu je následující test funkce aktivované protokolem HTTP:

Nejprve vytvořte <soubor project_root>/my_second_function/function.json a pak tuto funkci definujte jako trigger HTTP.

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

Dále můžete implementovat my_second_function a 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

Můžete začít psát testovací případy pro trigger HTTP.

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

.venv Ve složce virtuálního prostředí Pythonu nainstalujte oblíbenou testovací architekturu Pythonu, například pip install pytest. Potom spusťte kontrolu pytest tests výsledku testu.

Nejprve vytvořte <soubor project_root>/function_app.py a implementujte my_second_function funkci jako trigger HTTP a 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

Můžete začít psát testovací případy pro trigger HTTP.

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

Ve složce virtuálního prostředí .venv Pythonu nainstalujte oblíbenou testovací architekturu Pythonu, například pip install pytest. Potom spusťte kontrolu pytest tests výsledku testu.

Dočasné soubory

Metoda tempfile.gettempdir() vrátí dočasnou složku, která v Linuxu je /tmp. Aplikace může tento adresář použít k ukládání dočasných souborů generovaných a používaných funkcemi při jejich spuštění.

Důležité

Soubory zapsané do dočasného adresáře nejsou zaručeny, že se zachovají napříč vyvoláním. Během horizontálního navýšení kapacity se mezi instancemi nesdílí dočasné soubory.

Následující příklad vytvoří pojmenovaný dočasný soubor v dočasném adresáři (/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)

Doporučujeme udržovat testy ve složce, která je oddělená od složky projektu. Tato akce vám umožní nasadit testovací kód s vaší aplikací.

Předinstalované knihovny

K dispozici je několik knihoven s modulem runtime funkcí Pythonu.

Standardní knihovna Pythonu

Standardní knihovna Pythonu obsahuje seznam integrovaných modulů Pythonu, které se dodávají s každou distribucí Pythonu. Většina těchto knihoven vám pomůže získat přístup k funkcím systému, jako je vstup/výstup souboru (vstupně-výstupní operace). V systémech Windows se tyto knihovny instalují s Pythonem. V systémech Unix jsou poskytovány kolekcemi balíčků.

Pokud chcete zobrazit knihovnu pro vaši verzi Pythonu, přejděte na:

Závislosti pracovních procesů Azure Functions v Pythonu

Pracovní proces Azure Functions v Pythonu vyžaduje konkrétní sadu knihoven. Tyto knihovny můžete použít také ve svých funkcích, ale nejsou součástí standardu Pythonu. Pokud vaše funkce spoléhají na některou z těchto knihoven, může být pro váš kód nedostupný, když běží mimo Službu Azure Functions.

Poznámka:

Pokud soubor requirements.txt vaší aplikace funkcí obsahuje azure-functions-worker položku, odeberte ji. Pracovní proces functions je automaticky spravován platformou Azure Functions a pravidelně ho aktualizujeme novými funkcemi a opravami chyb. Ruční instalace staré verze pracovního procesu v souboru requirements.txt může způsobit neočekávané problémy.

Poznámka:

Pokud váš balíček obsahuje určité knihovny, které můžou kolidovat se závislostmi pracovního procesu (například protobuf, tensorflow nebo grpcio), nakonfigurujte PYTHON_ISOLATE_WORKER_DEPENDENCIES 1 v nastavení aplikace tak, aby aplikace nemohla odkazovat na závislosti pracovního procesu.

Knihovna Pythonu pro Azure Functions

Každá aktualizace pracovního procesu Pythonu zahrnuje novou verzi knihovny Pythonu Azure Functions (azure.functions). Tento přístup usnadňuje nepřetržitou aktualizaci aplikací funkcí Pythonu, protože každá aktualizace je zpětně kompatibilní. Seznam verzí této knihovny najdete v části Azure-Functions PyPi.

Verze knihovny modulu runtime je opravená v Azure a nejde ji přepsat requirements.txt. Položka azure-functions v requirements.txt je určená pouze pro lintování a informovanost zákazníků.

Ke sledování skutečné verze knihovny funkcí Pythonu v modulu runtime použijte následující kód:

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

Systémové knihovny modulu runtime

Seznam předinstalovaných systémových knihoven v imagích Dockeru pracovních procesů Pythonu najdete tady:

Modul runtime služby Functions Verze Debianu Verze Pythonu
Verze 3.x Chlapík Python 3.7
Python 3.8
Python 3.9

Rozšíření pracovních procesů Pythonu

Pracovní proces Pythonu, který běží ve službě Azure Functions, umožňuje integrovat knihovny třetích stran do vaší aplikace funkcí. Tyto rozšiřující knihovny fungují jako middleware, který může během životního cyklu provádění vaší funkce vkládat konkrétní operace.

Rozšíření se do kódu funkce importují podobně jako standardní modul knihovny Pythonu. Rozšíření se spouští na základě následujících oborů:

Scope Popis
Úroveň aplikace Při importu do libovolné aktivační události funkce se rozšíření vztahuje na každé spuštění funkce v aplikaci.
Úroveň funkce Spouštění je omezené jenom na konkrétní aktivační událost funkce, do které se importuje.

Další informace o oboru, ve kterém rozšíření běží, najdete v informacích o jednotlivých rozšířeních.

Rozšíření implementují rozhraní rozšíření pracovního procesu Pythonu. Tato akce umožňuje volání pracovního procesu Pythonu do kódu rozšíření během životního cyklu provádění funkce. Další informace najdete v tématu Vytváření rozšíření.

Použití rozšíření

V funkcích Pythonu můžete použít knihovnu rozšíření pracovních procesů Pythonu následujícím způsobem:

  1. Přidejte balíček přípony do souboru requirements.txt projektu.
  2. Nainstalujte knihovnu do aplikace.
  3. Přidejte následující nastavení aplikace:
    • Místně: Zadejte "PYTHON_ENABLE_WORKER_EXTENSIONS": "1" do části souboru local.settings.json.Values
    • Azure: Zadejte PYTHON_ENABLE_WORKER_EXTENSIONS=1 do nastavení aplikace.
  4. Importujte modul rozšíření do triggeru funkce.
  5. V případě potřeby nakonfigurujte instanci rozšíření. Požadavky na konfiguraci by se měly zobrazit v dokumentaci k rozšíření.

Důležité

Microsoft nepodporuje nebo zaručuje externí knihovny rozšíření pracovních procesů Pythonu. Musíte se ujistit, že všechna rozšíření, která používáte ve své aplikaci funkcí, jsou důvěryhodná a nesete úplné riziko použití škodlivého nebo špatně napsaného rozšíření.

Třetí strany by měly poskytnout konkrétní dokumentaci k instalaci a využívání jejich rozšíření ve vaší aplikaci funkcí. Základní příklad využití rozšíření najdete v tématu Využití rozšíření.

Tady jsou příklady použití rozšíření v aplikaci funkcí podle oboru:

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

Vytváření rozšíření

Rozšíření vytvářejí vývojáři knihoven třetích stran, kteří vytvořili funkce, které je možné integrovat do Azure Functions. Vývojář rozšíření navrhuje, implementuje a vydává balíčky Pythonu, které obsahují vlastní logiku navrženou speciálně pro spuštění v kontextu provádění funkcí. Tato rozšíření je možné publikovat buď do registru PyPI, nebo do úložišť GitHub.

Informace o vytváření, balení, publikování a využívání balíčku rozšíření pracovního procesu Pythonu najdete v tématu Vývoj rozšíření pracovních procesů Pythonu pro Azure Functions.

Rozšíření na úrovni aplikace

Rozšíření zděděné z AppExtensionBase běhů v oboru aplikace .

AppExtensionBase zveřejňuje následující abstraktní metody třídy, které můžete implementovat:

metoda Popis
init Volá se po importu rozšíření.
configure Volá se z kódu funkce, když je potřeba nakonfigurovat rozšíření.
post_function_load_app_level Volá se hned po načtení funkce. Do rozšíření se předá název funkce a adresář funkce. Mějte na paměti, že adresář funkce je jen pro čtení a všechny pokusy o zápis do místního souboru v tomto adresáři selžou.
pre_invocation_app_level Volané přímo před aktivací funkce. Do rozšíření se předají kontext funkce a argumenty vyvolání funkce. Obvykle můžete předat další atributy v kontextovém objektu, aby kód funkce mohl využívat.
post_invocation_app_level Volá se hned po dokončení provádění funkce. Kontext funkce, argumenty vyvolání funkce a návratový objekt vyvolání se předají rozšíření. Tato implementace je dobrým místem k ověření, jestli bylo spuštění zachytávků životního cyklu úspěšné.

Rozšíření na úrovni funkce

Rozšíření, které dědí z FuncExtensionBase běží v konkrétní aktivační události funkce.

FuncExtensionBase zveřejňuje následující abstraktní metody třídy pro implementace:

metoda Popis
__init__ Konstruktor rozšíření. Volá se, když je instance rozšíření inicializována v konkrétní funkci. Při implementaci této abstraktní metody můžete chtít přijmout filename parametr a předat ho metodě nadřazeného objektu super().__init__(filename) pro správnou registraci rozšíření.
post_function_load Volá se hned po načtení funkce. Do rozšíření se předá název funkce a adresář funkce. Mějte na paměti, že adresář funkce je jen pro čtení a všechny pokusy o zápis do místního souboru v tomto adresáři selžou.
pre_invocation Volané přímo před aktivací funkce. Do rozšíření se předají kontext funkce a argumenty vyvolání funkce. Obvykle můžete předat další atributy v kontextovém objektu, aby kód funkce mohl využívat.
post_invocation Volá se hned po dokončení provádění funkce. Kontext funkce, argumenty vyvolání funkce a návratový objekt vyvolání se předají rozšíření. Tato implementace je dobrým místem k ověření, jestli bylo spuštění zachytávků životního cyklu úspěšné.

Sdílení prostředků různého původu

Azure Functions podporuje sdílení prostředků mezi zdroji (CORS). CORS se konfiguruje na portálu a prostřednictvím Azure CLI. Seznam povolených zdrojů CORS se vztahuje na úrovni aplikace funkcí. S povoleným CORS zahrnují odpovědi hlavičku Access-Control-Allow-Origin . Další informace naleznete v tématu Sdílení prostředků různého původu.

Sdílení prostředků mezi zdroji (CORS) je plně podporováno pro aplikace funkcí Pythonu.

Async

Ve výchozím nastavení může instance hostitele pro Python zpracovat pouze jedno vyvolání funkce najednou. Důvodem je, že Python je modul runtime s jedním vláknem. U aplikace funkcí, která zpracovává velký počet vstupně-výstupních událostí nebo je vázaná na vstupně-výstupní operace, můžete výrazně zlepšit výkon spouštěním funkcí asynchronně. Další informace najdete v tématu Vylepšení výkonu aplikací Pythonu ve službě Azure Functions.

Sdílená paměť (Preview)

Kvůli zlepšení propustnosti umožňuje Azure Functions, aby váš pracovní proces jazyka Pythonu mimo proces sdílel paměť s hostitelským procesem Functions. Když aplikace funkcí naráží na kritické body, můžete povolit sdílenou paměť přidáním nastavení aplikace s názvem FUNCTIONS_WORKER_SHARED_MEMORY_DATA_TRANSFER_ENABLED s hodnotou 1. Když je povolená sdílená paměť, můžete pomocí nastavení DOCKER_SHM_SIZE nastavit sdílenou paměť na něco podobného 268435456, což odpovídá 256 MB.

Můžete například povolit sdílenou paměť, abyste snížili kritické body při použití vazeb Blob Storage k přenosu datových částí větších než 1 MB.

Tato funkce je dostupná jenom pro aplikace funkcí, které běží v plánech Premium a Dedicated (Aplikace Azure Service). Další informace najdete v tématu Sdílená paměť.

Známé problémy a nejčastější dotazy

Tady jsou dva průvodci odstraňováním potíží pro běžné problémy:

Tady jsou dva průvodci odstraňováním potíží se známými problémy s programovacím modelem v2:

Všechny známé problémy a žádosti o funkce se sledují v seznamu problémů GitHubu. Pokud narazíte na problém a nemůžete problém najít na GitHubu, otevřete nový problém a uveďte podrobný popis problému.

Další kroky

Další informace naleznete v následujících zdrojích:

Máte problémy s používáním Pythonu? Řekněte nám, co se děje.