Azure Functions Python Developer Guide (Справочник по Функциям Azure для разработчика Python)
Это руководство содержит общие сведения о разработке Функции Azure с помощью Python. В статье предполагается, что вы уже ознакомились с руководством разработчиков Функции Azure.
Внимание
Эта статья поддерживает модель программирования версии 1 и версии 2 для Python в Функции Azure. Модель Python версии 1 использует файл functions.json для определения функций, а новая модель версии 2 позволяет вместо этого использовать подход на основе декоратора. Этот новый подход приводит к более простой структуре файлов, и она более ориентирована на код. Выберите селектор версии 2 в верхней части статьи, чтобы узнать об этой новой модели программирования.
Разработчик Python также может быть заинтересован в следующих разделах:
- Visual Studio Code: создайте первое приложение Python с помощью Visual Studio Code.
- Терминал или командная строка: создайте первое приложение Python из командной строки с помощью Функции Azure Core Tools.
- Примеры. Просмотрите некоторые существующие приложения Python в браузере примеров Learn.
- Visual Studio Code: создайте первое приложение Python с помощью Visual Studio Code.
- Терминал или командная строка: создайте первое приложение Python из командной строки с помощью Функции Azure Core Tools.
- Примеры. Просмотрите некоторые существующие приложения Python в браузере примеров Learn.
Варианты разработки
Обе модели программирования функций Python поддерживают локальную разработку в одной из следующих сред:
Модель программирования Python версии 2:
Модель программирования Python версии 1:
Вы также можете создать функции Python версии 1 в портал Azure.
Совет
Хотя вы можете разрабатывать функции Azure на основе Python локально в Windows, Python поддерживается только в плане размещения на основе Linux при работе в Azure. Дополнительные сведения см. в списке поддерживаемых сочетаний операционной системы и среды выполнения.
Модель программирования
Функция Azure должна быть реализована как метод без отслеживания состояния в сценарии Python, который обрабатывает входные данные и создает выходные данные. По умолчанию среда выполнения ожидает, что метод будет реализован в виде глобального метода, вызываемого main()
в файле __init__.py . Можно также указать альтернативную точку входа.
Вы привязываете данные к функции из триггеров и привязок с помощью атрибутов метода, использующих свойство, name
определенное в файле function.json . Например, следующий файл function.json описывает простую функцию, активированную HTTP-запросом req
:
{
"scriptFile": "__init__.py",
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
]
}
На основе этого определения файл __init__.py, содержащий код функции, может выглядеть следующим образом:
def main(req):
user = req.params.get('user')
return f'Hello, {user}!'
Также можно явно объявить для функции типы атрибутов и тип возвращаемого значения с помощью аннотации типов Python. Это помогает использовать функции IntelliSense и автозавершения, предоставляемые многими редакторами кода Python.
import azure.functions
def main(req: azure.functions.HttpRequest) -> str:
user = req.params.get('user')
return f'Hello, {user}!'
Используйте заметки Python, включенные в пакет azure.functions.* для привязки входных и выходных данных к методам.
Функция Azure должна быть реализована как метод без отслеживания состояния в сценарии Python, который обрабатывает входные данные и создает выходные данные. По умолчанию среда выполнения ожидает, что метод будет реализован как глобальный метод в файле function_app.py .
Триггеры и привязки можно объявлять и использовать в функции в подходе на основе декоратора. Они определены в том же файле, function_app.py, что и функции. Например, следующий function_app.py-файл представляет триггер функции http-запросом.
@app.function_name(name="HttpTrigger1")
@app.route(route="req")
def main(req):
user = req.params.get("user")
return f"Hello, {user}!"
Также можно явно объявить для функции типы атрибутов и тип возвращаемого значения с помощью аннотации типов Python. Это помогает использовать функции IntelliSense и функции автозаполнения, предоставляемые многими редакторами кода Python.
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}!"
Сведения об известных ограничениях модели версии 2 и их обходных решениях см. в статье "Устранение ошибок Python в Функции Azure".
Альтернативная точка входа
Можно изменить поведение функции по умолчанию, при необходимости указав свойства scriptFile
и entryPoint
в файле function.json. Например, следующая function.json сообщает среде выполнения использовать customentry()
метод в файле main.py в качестве точки входа для функции Azure.
{
"scriptFile": "main.py",
"entryPoint": "customentry",
"bindings": [
...
]
}
Точка входа находится только в файле function_app.py . Однако можно ссылаться на функции в проекте в function_app.py с помощью схем или импорта.
Структура папок
Рекомендуемая структура папок для проекта функций Python выглядит следующим образом:
<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
Основная папка проекта, <project_root>, может содержать следующие файлы:
- local.settings.json. Используется для хранения параметров приложения и строка подключения при локальном запуске. Этот файл не публикуется в Azure. Дополнительные сведения см. в разделе local.settings.file.
- requirements.txt: содержит список пакетов, которые должны быть установлены при публикации в Azure.
- host.json: содержит параметры глобальной конфигурации, влияющие на все функции в экземпляре приложения-функции. Этот файл не публикуется в Azure. При локальном запуске поддерживаются не все параметры. Дополнительные сведения см. в разделе host.json.
- VSCODE/: (Необязательно) Содержит хранимую конфигурацию Visual Studio Code. Дополнительные сведения см. в разделе параметров Visual Studio Code.
- .venv/: (необязательно) Содержит виртуальную среду Python, используемую локальной разработкой.
- Dockerfile: (необязательно) используется при публикации проекта в настраиваемом контейнере.
- tests/: (необязательно) Содержит тест-кейсы для вашего приложения-функции.
- .funcignore: (необязательно) объявляет файлы, которые не должны публиковаться в Azure. Обычно этот файл содержит vscode/ , чтобы игнорировать параметры редактора, .venv/ , чтобы игнорировать локальную виртуальную среду Python, тесты или игнорировать тестовые случаи и local.settings.json , чтобы предотвратить публикацию параметров локального приложения.
Каждая функция имеет собственный файл кода и файл конфигурации привязки, function.json.
Рекомендуемая структура папок для проекта функций Python выглядит следующим образом:
<project_root>/
| - .venv/
| - .vscode/
| - function_app.py
| - additional_functions.py
| - tests/
| | - test_my_function.py
| - .funcignore
| - host.json
| - local.settings.json
| - requirements.txt
| - Dockerfile
Основная папка проекта, <project_root>, может содержать следующие файлы:
- .venv/: (необязательно) Содержит виртуальную среду Python, которая используется локальной разработкой.
- VSCODE/: (Необязательно) Содержит хранимую конфигурацию Visual Studio Code. Дополнительные сведения см. в разделе параметров Visual Studio Code.
- function_app.py. Расположение по умолчанию для всех функций и связанных с ними триггеров и привязок.
- additional_functions.py: (необязательно) Любые другие файлы Python, содержащие функции (обычно для логической группировки), на которые ссылаются function_app.py с помощью схем.
- tests/: (необязательно) Содержит тест-кейсы для вашего приложения-функции.
- .funcignore: (необязательно) объявляет файлы, которые не должны публиковаться в Azure. Как правило, этот файл содержит vscode/, чтобы игнорировать параметр редактора, venv/, чтобы игнорировать локальную виртуальную среду Python, тесты или игнорировать тестовые случаи и local.settings.json, чтобы предотвратить публикацию параметров локального приложения.
- host.json: содержит параметры глобальной конфигурации, влияющие на все функции в экземпляре приложения-функции. Этот файл не публикуется в Azure. При локальном запуске поддерживаются не все параметры. Дополнительные сведения см. в разделе host.json.
- local.settings.json. Используется для хранения параметров приложения и строка подключения при локальном запуске. Этот файл не публикуется в Azure. Дополнительные сведения см. в разделе local.settings.file.
- requirements.txt. Содержит список пакетов Python, которые система устанавливает при публикации в Azure.
- Dockerfile: (необязательно) используется при публикации проекта в настраиваемом контейнере.
При развертывании проекта в приложении-функции в Azure все содержимое основной папки <проекта, project_root>, должно быть включено в пакет, но не в саму папку, что означает, что host.json должен находиться в корневом каталоге пакета. Рекомендуется поддерживать тесты в папке вместе с другими функциями (в этом примере — тесты/). Дополнительные сведения см. в разделе Модульное тестирование.
Соединение с базой данных
Функции Azure хорошо интегрируется с Azure Cosmos DB для многих вариантов использования, включая IoT, электронную коммерцию, игры и т. д.
Например, для источника событий две службы интегрированы в архитектуры, управляемые событиями, с помощью функции канала изменений Azure Cosmos DB. Канал изменений предоставляет нижестоящим микрослужбам возможность надежного и добавочного чтения вставок и обновлений (например, событий заказа). Эту функцию можно использовать для предоставления постоянного хранилища событий в качестве брокера сообщений для событий изменения состояния и рабочего процесса обработки заказа диска между многими микрослужбами (которые можно реализовать как бессерверные Функции Azure).
Чтобы подключиться к Azure Cosmos DB, сначала создайте учетную запись, базу данных и контейнер. Затем можно подключить код функции к Azure Cosmos DB с помощью триггеров и привязок, как показано в этом примере.
Для реализации более сложной логики приложения можно также использовать библиотеку Python для Cosmos DB. Реализация асинхронного ввода-вывода выглядит следующим образом:
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
Модель программирования Python версии 2 представляет концепцию схем. Схема — это новый класс, созданный для регистрации функций вне основного приложения-функции. Функции, зарегистрированные в экземплярах схемы, не индексируются непосредственно средой выполнения функции. Чтобы получить индексированные эти функции схемы, приложение-функция должна зарегистрировать функции из экземпляров схемы.
Использование схем обеспечивает следующие преимущества:
- Позволяет разбить приложение-функцию на модульные компоненты, что позволяет определять функции в нескольких файлах Python и разделять их на разные компоненты на файл.
- Предоставляет расширяемые интерфейсы приложений-функций для создания и повторного использования собственных API.
В следующем примере показано, как использовать схемы:
Во-первых, в файле http_blueprint.py функция с триггером HTTP сначала определяется и добавляется в объект схемы.
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
)
Затем в файле function_app.py объект схемы импортируется и его функции регистрируются в приложении-функции.
import azure.functions as func
from http_blueprint import bp
app = func.FunctionApp()
app.register_functions(bp)
Примечание.
Устойчивые функции также поддерживает схемы. Чтобы создать схемы для приложений Устойчивые функции, зарегистрируйте оркестрацию, действие и триггеры сущностей и привязки клиента с помощью azure-functions-durable
Blueprint
класса, как показано здесь. После этого результирующая схема может быть зарегистрирована как обычная. Пример см. в нашем примере .
Поведение при импорте
Вы можете импортировать модули в код функции, используя явные относительные и абсолютные ссылки. На основе ранее описанной структуры папок следующие импорты работают в файле <функции 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)
Примечание.
При использовании абсолютного синтаксиса импорта shared_code/ папка должна содержать файл __init__.py, чтобы пометить его как пакет Python.
Следующие __app__ импорта и за пределами относительного импорта верхнего уровня устарели, так как они не поддерживаются средство проверки статических типов и не поддерживаются платформами тестирования Python:
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)
Триггеры и входные данные
Входные данные в Функциях Azure делятся на две категории: входные данные триггеров и другие входные данные. Хотя они отличаются в файле function.json, их использование идентично в коде Python. Строки подключения или секреты для источников триггеров и входных данных сопоставляются со значениями в файле local.settings.json при локальном запуске и сопоставляются с параметрами приложения при их запуске в Azure.
Например, следующий код демонстрирует разницу между двумя входными данными:
// 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()}')
При активации этой функции HTTP-запрос передается в функцию с помощью req
. Запись извлекается из учетной записи Хранилище BLOB-объектов Azure на основе идентификатора в URL-адресе маршрута и предоставляется как obj
в тексте функции. Здесь указанная учетная запись хранения — это строка подключения, найденный в параметре CONNECTION_STRING
приложения.
Входные данные в Функциях Azure делятся на две категории: входные данные триггеров и другие входные данные. Хотя они определены с помощью разных декораторов, их использование аналогично в коде Python. Строки подключения или секреты для источников триггеров и входных данных сопоставляются со значениями в файле local.settings.json при локальном запуске и сопоставляются с параметрами приложения при их запуске в Azure.
Например, в следующем коде показано, как определить входную привязку хранилища BLOB-объектов:
// 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()}')
При активации этой функции HTTP-запрос передается в функцию с помощью req
. Запись извлекается из учетной записи Хранилище BLOB-объектов Azure на основе идентификатора в URL-адресе маршрута и предоставляется как obj
в тексте функции. Здесь указанная учетная запись хранения — это строка подключения, найденный в параметре STORAGE_CONNECTION_STRING
приложения.
Для операций с интенсивной привязкой данных может потребоваться использовать отдельную учетную запись хранения. Дополнительные сведения см . в руководстве по учетной записи хранения.
Привязки типов ПАКЕТА SDK (предварительная версия)
Для выбора триггеров и привязок можно работать с типами данных, реализованными базовыми пакетами SDK и платформами Azure. Эти привязки типов SDK позволяют взаимодействовать с данными привязки , как если бы вы использовали базовый пакет SDK службы.
Внимание
Для поддержки привязок типов SDK требуется модель программирования Python версии 2.
Функции поддерживают привязки типов пакета SDK Python для хранилища BLOB-объектов Azure, что позволяет работать с данными BLOB-объектов с помощью базового BlobClient
типа.
Внимание
Поддержка привязок типов ПАКЕТА SDK для Python в настоящее время доступна в предварительной версии:
- Необходимо использовать модель программирования Python версии 2.
- В настоящее время поддерживаются только синхронные типы sdk.
Необходимые компоненты
- Функции Azure среды выполнения версии 4.34 или более поздней версии.
- Python версии 3.9 или более поздней поддерживаемой версии.
Включение привязок типов ПАКЕТА SDK для расширения хранилища BLOB-объектов
azurefunctions-extensions-bindings-blob
Добавьте пакетrequirements.txt
расширения в файл в проекте, который должен включать по крайней мере следующие пакеты:azure-functions azurefunctions-extensions-bindings-blob
Добавьте этот код
function_app.py
в файл в проекте, который импортирует привязки типов пакета SDK:import azurefunctions.extensions.bindings.blob as blob
Примеры привязок типов ПАКЕТА SDK
В этом примере показано, как получить BlobClient
от триггера хранилища BLOB-объектов (blob_trigger
) и из входной привязки для триггера 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"
Вы можете просмотреть другие примеры привязок типов пакета SDK для хранилища BLOB-объектов в репозитории расширений Python:
HTTP-потоки (предварительная версия)
Потоки HTTP позволяют принимать и возвращать данные из конечных точек HTTP с помощью API запросов FastAPI и ответов, включенных в ваших функциях. Эти API позволяют узлу обрабатывать большие данные в HTTP-сообщениях как блоки вместо чтения всего сообщения в память.
Эта функция позволяет обрабатывать большой поток данных, интеграции OpenAI, предоставлять динамическое содержимое и поддерживать другие основные сценарии HTTP, требующие взаимодействия в режиме реального времени по протоколу HTTP. Можно также использовать типы ответов FastAPI с HTTP-потоками. Без потоков HTTP размер HTTP-запросов и ответов ограничен ограничениями памяти, которые могут возникнуть при обработке всех полезных данных сообщения во всей памяти.
Внимание
Для поддержки потоков HTTP требуется модель программирования Python версии 2.
Внимание
Поддержка потоков HTTP для Python в настоящее время доступна в предварительной версии и требует использования модели программирования Python версии 2.
Необходимые компоненты
- Функции Azure среды выполнения версии 4.34.1 или более поздней версии.
- Python версии 3.8 или более поздней поддерживаемой версии.
Включение потоков HTTP
Http-потоки по умолчанию отключены. Эту функцию необходимо включить в параметрах приложения, а также обновить код для использования пакета FastAPI. Обратите внимание, что при включении потоков HTTP приложение-функция по умолчанию будет использовать потоковую передачу HTTP, а исходная функция HTTP не будет работать.
azurefunctions-extensions-http-fastapi
Добавьте пакетrequirements.txt
расширения в файл в проекте, который должен включать по крайней мере следующие пакеты:azure-functions azurefunctions-extensions-http-fastapi
Добавьте этот код
function_app.py
в файл в проекте, который импортирует расширение FastAPI:from azurefunctions.extensions.http.fastapi import Request, StreamingResponse
При развертывании в Azure добавьте следующий параметр приложения в приложение-функцию:
"PYTHON_ENABLE_INIT_INDEXING": "1"
При развертывании в потреблении Linux также добавьте
"PYTHON_ISOLATE_WORKER_DEPENDENCIES": "1"
При локальном запуске также необходимо добавить эти же параметры в
local.settings.json
файл проекта.
Примеры потоков HTTP
После включения функции потоковой передачи HTTP можно создать функции, которые передают данные по протоколу HTTP.
В этом примере показана функция, активировающая HTTP, которая передает данные ответа HTTP. Эти возможности можно использовать для поддержки таких сценариев, как отправка данных событий через конвейер для визуализации в режиме реального времени или обнаружения аномалий в больших наборах данных и предоставления мгновенных уведомлений.
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")
В этом примере активируется функция HTTP, которая получает и обрабатывает потоковую передачу данных от клиента в режиме реального времени. Он демонстрирует возможности потоковой передачи, которые могут быть полезны для сценариев, таких как обработка непрерывных потоков данных и обработка данных событий с устройств Интернета вещей.
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-потоков
Для выполнения потоковых вызовов к конечным точкам FastAPI функции необходимо использовать клиентскую библиотеку HTTP. Клиентское средство или браузер, который вы используете, может не поддерживать потоковую передачу или возвращать только первый блок данных.
Для отправки потоковых данных в конечную точку HTTP можно использовать клиентский скрипт:
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())
Выходные данные
Выходные данные можно выразить как возвращаемое значение или параметры вывода. Если используется только один вывод, мы рекомендуем использовать возвращаемое значение. Для нескольких выходных данных необходимо использовать выходные параметры.
Чтобы использовать возвращаемое значение функции в качестве значения выходной привязки, name
свойство привязки должно быть задано $return
в файле function.json .
Чтобы создать несколько выходных значений, используйте метод set()
из интерфейса azure.functions.Out
, чтобы присвоить значение привязке. Например, следующая функция может направлять сообщение в очередь и возвращает ответ 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
Выходные данные можно выразить как возвращаемое значение или параметры вывода. Если используется только один вывод, мы рекомендуем использовать возвращаемое значение. Для нескольких выводов нужно использовать параметры вывода.
Чтобы создать несколько выходных значений, используйте метод set()
из интерфейса azure.functions.Out
, чтобы присвоить значение привязке. Например, следующая функция может направлять сообщение в очередь и возвращает ответ 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
Ведение журнала
Доступ к средству ведения журнала среды выполнения Функций Azure предоставляется через корневой обработчик logging
в приложении-функции. Это средство ведения журнала привязано к Application Insights и позволяет отмечать предупреждения и ошибки, которые возникают во время выполнения функции.
Следующий пример сохраняет в журнал информационное сообщение, когда функция вызывается с помощью триггера HTTP.
import logging
def main(req):
logging.info('Python HTTP trigger function processed a request.')
Доступны дополнительные методы ведения журнала, которые позволяют выводить сообщения в консоль на разных уровнях трассировки.
Метод | Description |
---|---|
critical(_message_) |
Записывает сообщение с уровнем CRITICAL в корневое средство ведения журнала. |
error(_message_) |
Записывает сообщение с уровнем ERROR в корневое средство ведения журнала. |
warning(_message_) |
Записывает сообщение с уровнем WARNING в корневое средство ведения журнала. |
info(_message_) |
Записывает сообщение с уровнем INFO в корневое средство ведения журнала. |
debug(_message_) |
Записывает сообщение с уровнем DEBUG в корневое средство ведения журнала. |
Дополнительные сведения о ведении журналов см. в статье Мониторинг Функций Azure.
Ведение журнала из созданных потоков
Чтобы просмотреть журналы, поступающие из созданных потоков, добавьте context
аргумент в подпись функции. Этот аргумент содержит атрибут thread_local_storage
, который хранит локальный invocation_id
. Это можно задать для текущей invocation_id
функции, чтобы убедиться, что контекст изменен.
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.')
Ведение журнала пользовательской телеметрии
По умолчанию среда выполнения Функций собирает журналы и другие данные телеметрии, созданные вашими функциями. Эти данные телеметрии завершаются как трассировки в Application Insights. Данные телеметрии запросов и зависимостей для определенных служб Azure также собираются по умолчанию с помощью триггеров и привязок.
Чтобы получить данные телеметрии пользовательских запросов и зависимостей (не через привязки), можно использовать расширения Python OpenCensus. Это расширение отправляет пользовательские данные телеметрии в ваш экземпляр Application Insights. Список поддерживаемых расширений можно найти в репозитории OpenCensus.
Примечание.
Чтобы использовать расширения Python OpenCensus, необходимо включить расширения рабочих ролей Python в приложении-функции, сменив в настройках PYTHON_ENABLE_WORKER_EXTENSIONS
на 1
. Кроме того, необходимо переключиться на использование строки подключения Application Insights, добавив APPLICATIONINSIGHTS_CONNECTION_STRING
параметр в параметры приложения, если он еще не задан.
// 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
Триггер HTTP определяется в файле function.json. name
привязки должен соответствовать именованному параметру в функции.
В предыдущих примерах используется имя привязки req
. Этот параметр является объектом HttpRequest, и возвращается объект HttpResponse.
Из объекта HttpRequest можно получить заголовки запроса, параметры запроса, параметры маршрута и текст сообщения.
Следующий пример относится к шаблону триггера HTTP для 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
)
В этой функции вы получаете значение name
параметра запроса из params
параметра объекта HttpRequest . Текст сообщения в кодировке JSON с помощью get_json
метода.
Аналогичным образом можно задать status_code
и headers
для ответного сообщения в возвращенном объекте HttpResponse.
Триггер HTTP определяется как метод, который принимает именованный параметр привязки, который является объектом HttpRequest и возвращает объект HttpResponse . Примените function_name
декоратор к методу для определения имени функции, а конечная точка HTTP устанавливается путем применения route
декоратора.
В этом примере используется шаблон триггера HTTP для модели программирования Python версии 2, где имя параметра привязки — req
. Это пример кода, который предоставляется при создании функции с помощью Функции Azure Core Tools или 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
)
Из объекта HttpRequest можно получить заголовки запроса, параметры запроса, параметры маршрута и текст сообщения. В этой функции вы получаете значение name
параметра запроса из params
параметра объекта HttpRequest . Текст сообщения в кодировке JSON с помощью get_json
метода.
Аналогичным образом можно задать status_code
и headers
для ответного сообщения в возвращенном объекте HttpResponse.
Чтобы передать имя в этом примере, вставьте URL-адрес, предоставленный при запуске функции, а затем добавьте его."?name={name}"
Веб-платформы
Интерфейс шлюза веб-сервера (WSGI)совместимый и асинхронный интерфейс шлюза сервера (ASGI), совместимые с платформами, такими как Flask и FastAPI, с функциями Python с триггером HTTP. В этом разделе показано, как изменить функции для поддержки этих платформ.
Сначала необходимо обновить файл function.json, чтобы включить route
его в триггер HTTP, как показано в следующем примере:
{
"scriptFile": "__init__.py",
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
],
"route": "{*route}"
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
]
}
Файл host.json также должен быть обновлен, чтобы включить HTTProutePrefix
, как показано в следующем примере:
{
"version": "2.0",
"logging":
{
"applicationInsights":
{
"samplingSettings":
{
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensionBundle":
{
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[3.*, 4.0.0)"
},
"extensions":
{
"http":
{
"routePrefix": ""
}
}
}
Обновите файл кода Python init.py в зависимости от интерфейса, используемого платформой. В следующем примере показан подход с использованием обработчика ASGI или подход с использованием WSGI-оболочки для Flask:
Вы можете использовать платформы, совместимые с асинхронным интерфейсом шлюза сервера (ASGI) и интерфейсом шлюза веб-сервера (WSGI), совместимыми с Flask и FastAPI, с функциями Python, активировав HTTP. Сначала необходимо обновить файл host.json , чтобы включить HTTP routePrefix
, как показано в следующем примере:
{
"version": "2.0",
"logging":
{
"applicationInsights":
{
"samplingSettings":
{
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensionBundle":
{
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[2.*, 3.0.0)"
},
"extensions":
{
"http":
{
"routePrefix": ""
}
}
}
Код платформы выглядит следующим образом:
AsgiFunctionApp
— это класс приложения-функции верхнего уровня для создания функций HTTP ASGI.
# 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)
Масштабирование и производительность
Рекомендации по масштабированию и производительности приложений-функций Python см. в статье о масштабировании и производительности Python.
Контекст
Чтобы получить контекст вызова функции при запуске, добавьте context
аргумент в подпись.
Например:
import azure.functions
def main(req: azure.functions.HttpRequest,
context: azure.functions.Context) -> str:
return f'{context.invocation_id}'
Класс Context
имеет следующие строковые атрибуты:
Атрибут | Description |
---|---|
function_directory |
Каталог, в котором выполняется функция. |
function_name |
Имя функции. |
invocation_id |
Идентификатор вызова текущей функции. |
thread_local_storage |
Локальное хранилище потока функции. Содержит локальный invocation_id объект для ведения журнала из созданных потоков. |
trace_context |
Контекст распределенной трассировки. Дополнительные сведения см. в разделе Trace Context . |
retry_context |
Контекст повторных попыток в функцию. Дополнительные сведения см. в разделе retry-policies . |
Глобальные переменные
Не гарантируется, что состояние приложения будет сохранено для будущих выполнений. Однако среда выполнения Функций Azure часто использует один и тот же процесс для нескольких выполнений одного и того же приложения. Чтобы кэшировать результаты дорогостоящих вычислений, объявите его как глобальную переменную.
CACHED_DATA = None
def main(req):
global CACHED_DATA
if CACHED_DATA is None:
CACHED_DATA = load_json()
# ... use CACHED_DATA in code
Переменные среды
В Функции Azure параметры приложения, такие как строка подключения службы, предоставляются в виде переменных среды при выполнении. Эти параметры в вашем коде доступны двумя основными способами.
Метод | Description |
---|---|
os.environ["myAppSetting"] |
Пытается получить параметр приложения по имени ключа и вызывает ошибку при неудачном выполнении. |
os.getenv("myAppSetting") |
Пытается получить параметр приложения по имени ключа и возвращается None , когда это не удалось. |
Оба этих способа должны объявляться import os
.
В следующем примере используется os.environ["myAppSetting"]
для получения параметра приложения по ключу с именем 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}')
Для локальной разработки параметры приложения сохраняются в файле local.settings.json.
В Функции Azure параметры приложения, такие как строка подключения службы, предоставляются в виде переменных среды при выполнении. Эти параметры в вашем коде доступны двумя основными способами.
Метод | Description |
---|---|
os.environ["myAppSetting"] |
Пытается получить параметр приложения по имени ключа и вызывает ошибку при неудачном выполнении. |
os.getenv("myAppSetting") |
Пытается получить параметр приложения по имени ключа и возвращается None , когда это не удалось. |
Оба этих способа должны объявляться import os
.
В следующем примере используется os.environ["myAppSetting"]
для получения параметра приложения по ключу с именем 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}')
Для локальной разработки параметры приложения сохраняются в файле local.settings.json.
Python version
Функции Azure поддерживают следующие версии Python:
Версия службы "Функции" | Версии Python* |
---|---|
4.x | 3.11 3,10 3,9 3,8 3,7 |
3.x | 3,9 3,8 3,7 |
* Официальные дистрибутивы Python
Чтобы запросить конкретную версию Python при создании приложения-функции в Azure, используйте параметр --runtime-version
команды az functionapp create
. Версия среды выполнения функций задается параметром --functions-version
. Версия Python устанавливается при создании приложения-функции и не может быть изменена для приложений, работающих в плане потребления.
Среда выполнения использует доступную версию Python при локальном запуске.
Изменение версии Python
Чтобы установить приложение-функцию Python для определенной версии языка, необходимо указать язык и версию языка в LinuxFxVersion
поле в конфигурации сайта. Например, чтобы изменить приложение Python на использование Python 3.8, установите значение linuxFxVersion
python|3.8
.
Сведения о том, как просматривать и изменять параметры сайта, см. в статье "Как настроить целевые linuxFxVersion
версии среды выполнения Функции Azure".
Дополнительные сведения см. в политике поддержки среды выполнения Функции Azure и поддерживаемых языках в Функции Azure.
Управление пакетами
При локальной разработке с помощью основных средств или Visual Studio Code добавьте имена и версии необходимых пакетов в файл requirements.txt , а затем установите их с помощью pip
.
Например, можно использовать следующий файл requirements.txt и pip
команду для установки requests
пакета из PyPI.
requests==2.19.1
pip install -r requirements.txt
При выполнении функций в плане Служба приложений зависимости, определенные в requirements.txt, имеют приоритет над встроенными модулями Python, такими какlogging
. Это приоритет может привести к конфликтам, если встроенные модули имеют те же имена, что и каталоги в коде. При выполнении плана потребления или плана Elastic Premium конфликты могут быть менее вероятными, так как зависимости по умолчанию не определяются приоритетами.
Чтобы предотвратить проблемы, выполняемые в плане Служба приложений, не назовите каталоги так же, как и любые собственные модули Python и не включают собственные библиотеки Python в файл requirements.txt проекта.
Публикация в Azure
Когда все будет готово к публикации, убедитесь, что все общедоступные зависимости перечислены в файле requirements.txt. Этот файл можно найти в корне каталога проекта.
Файлы и папки проекта, исключенные из публикации, включая папку виртуальной среды, можно найти в корневом каталоге проекта.
Для публикации проекта Python в Azure поддерживаются три действия сборки: удаленная сборка, локальная сборка и сборки с использованием пользовательских зависимостей.
Вы также можете использовать Azure Pipelines для создания зависимостей и публикации с помощью непрерывной поставки (CD). Дополнительные сведения см. в статье о непрерывной доставке с помощью Azure Pipelines.
Удаленная сборка
При использовании удаленной сборки зависимости, которые восстанавливаются на сервере и собственных зависимостях, соответствуют рабочей среде. Это приводит к уменьшению размера пакета развертывания. Используйте удаленную сборку при разработке приложений Python в Windows. Если в проекте есть пользовательские зависимости, можно использовать удаленную сборку с дополнительным URL-адресом индекса.
Зависимости получаются удаленно на основе содержимого файла requirements.txt. В качестве рекомендуемого метода сборки рекомендуется использовать удаленную сборку. По умолчанию Core Tools запрашивает удаленную сборку при использовании следующей func azure functionapp publish
команды для публикации проекта Python в Azure.
func azure functionapp publish <APP_NAME>
Не забудьте заменить <APP_NAME>
именем приложения-функции, размещенного в Azure.
Расширение Функций Azure для Visual Studio Code также запрашивает удаленную сборку по умолчанию.
Локальная сборка
Зависимости получаются локально на основе содержимого файла requirements.txt. Вы можете предотвратить выполнение удаленной сборки с помощью следующей func azure functionapp publish
команды для публикации с помощью локальной сборки:
func azure functionapp publish <APP_NAME> --build local
Не забудьте заменить <APP_NAME>
именем приложения-функции, размещенного в Azure.
При использовании --build local
параметра зависимости проекта считываются из файла requirements.txt , а эти зависимые пакеты загружаются и устанавливаются локально. Файлы проекта и зависимости развертываются с локального компьютера в Azure. Это приводит к увеличению пакета развертывания, отправляемого в Azure. Если по какой-то причине вы не можете получить файл requirements.txt с помощью основных инструментов, необходимо использовать параметр пользовательских зависимостей для публикации.
При локальной разработке в Windows не рекомендуется использовать локальные сборки.
Настраиваемые зависимости.
Если в проекте есть зависимости, которые не найдены в индексе пакетов Python, можно создать проект двумя способами. Первый способ, метод сборки, зависит от того, как вы создаете проект.
Удаленная сборка с дополнительным URL-адресом индекса
Если пакеты доступны из доступного индекса настраиваемого пакета, используйте удаленную сборку. Перед публикацией обязательно создайте параметр приложения с именем PIP_EXTRA_INDEX_URL
. Значение этого параметра — это URL-адрес пользовательского индекса пакета. При использовании этого параметра удаленная сборка будет выполняться pip install
с помощью --extra-index-url
параметра. Дополнительные сведения см. в документации по Pythonpip install
.
Вы также можете использовать учетные данные обычной проверки подлинности с дополнительными URL-адресами индексов пакетов. Дополнительные сведения см . в документации по Python по базовым учетным данным проверки подлинности.
Установка локальных пакетов
Если в проекте используются пакеты, которые недоступны для наших инструментов, их можно сделать доступными для приложения, поместив их в каталог __app__/.python_packages . Перед публикацией выполните следующую команду, чтобы установить зависимости локально:
pip install --target="<PROJECT_DIR>/.python_packages/lib/site-packages" -r requirements.txt
При использовании пользовательских зависимостей следует использовать --no-build
параметр публикации, так как вы уже установили зависимости в папку проекта.
func azure functionapp publish <APP_NAME> --no-build
Не забудьте заменить <APP_NAME>
именем приложения-функции, размещенного в Azure.
Модульное тестирование
Функции, написанные на Python, можно протестировать, как и другой код Python с помощью стандартных платформ тестирования. Для большинства привязок можно создать макет объекта ввода, создав экземпляр соответствующего класса из пакета azure.functions
. azure.functions
Так как пакет недоступен сразу же, не забудьте установить его с помощью файла requirements.txt, как описано в разделе управления пакетами выше.
При использовании my_second_function в качестве примера ниже приведен макетный тест функции, активируемой HTTP:
Сначала создайте <файл project_root>/my_second_function/function.json , а затем определите эту функцию как триггер HTTP.
{
"scriptFile": "__init__.py",
"entryPoint": "main",
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "$return"
}
]
}
Далее можно реализовать my_second_function
и 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
Вы можете начать писать тестовые случаи для триггера 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
В папке виртуальной среды Python установите любимую платформу тестов Python, напримерpip install pytest
. Затем выполните команду pytest tests
, чтобы проверить результат тестирования.
Сначала создайте файл project_root/function_app.py и реализуйте <функцию my_second_function
в качестве триггера HTTP и 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
Вы можете начать писать тестовые случаи для триггера 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',
)
В папке виртуальной среды Python venv установите любимую платформу тестов Python, напримерpip install pytest
. Затем выполните команду pytest tests
, чтобы проверить результат тестирования.
Временные файлы
Метод tempfile.gettempdir()
возвращает временную папку. В Linux это /tmp. Приложение может использовать этот каталог для хранения временных файлов, созданных и используемых функциями при их запуске.
Внимание
Файлы, записанные во временный каталог, не всегда сохраняются между вызовами. Во время масштабирования временные файлы не используются совместно экземплярами.
В следующем примере показано создание именованного временного файла во временном каталоге (/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)
Тесты рекомендуется хранить в папке, отдельной от папки проекта. Это действие позволяет не развертывать тестовый код в приложении.
Предустановленные библиотеки
Некоторые библиотеки входят в среду выполнения функций Python.
Стандартная библиотека Python
Стандартная библиотека Python содержит список встроенных модулей Python, которые поставляются с каждым дистрибутивом Python. Большинство этих библиотек помогают получить доступ к системным функциям, таким как входные и выходные данные файлов (ввода-вывода). В системах Windows эти библиотеки устанавливаются с Python. В системах под управлением Unix они предоставляются коллекциями пакетов.
Чтобы просмотреть библиотеку для версии Python, перейдите к следующим причинам:
- Стандартная библиотека Python 3.8
- Стандартная библиотека Python 3.9
- Стандартная библиотека Python 3.10
- Стандартная библиотека Python 3.11
Зависимости рабочих ролей Python в функциях Azure
Для рабочей роли Python Функции Azure требуется определенный набор библиотек. Эти библиотеки также можно использовать в функциях, но они не являются частью стандарта Python. Если функции полагаются на любую из этих библиотек, они могут быть недоступны для кода при запуске вне Функции Azure.
Примечание.
Если файл requirements.txt приложения-функции содержит запись azure-functions-worker
, удалите ее. Рабочая роль функций автоматически управляется платформой Функции Azure, и мы регулярно обновляем ее с помощью новых функций и исправлений ошибок. Установка старой версии рабочей роли в файле requirements.txt может привести к непредвиденным проблемам.
Примечание.
Если пакет содержит определенные библиотеки, которые могут столкнуться с зависимостями рабочей роли (например, protobuf, tensorflow или grpcio), настройте их PYTHON_ISOLATE_WORKER_DEPENDENCIES
1
в параметрах приложения, чтобы предотвратить обращение приложения к зависимостям рабочей роли.
Библиотека Python Функции Azure
Каждое обновление рабочей роли Python включает новую версию библиотеки Python Функции Azure (azure.functions). Такой подход упрощает непрерывное обновление приложений-функций Python, так как каждое обновление имеет обратную совместимость. Список выпусков этой библиотеки см. в azure-functions PyPi.
Версия библиотеки среды выполнения исправлена Azure, и ее нельзя переопределить requirements.txt. Запись azure-functions
в файле requirements.txt относится только к анализу кода и предоставлена к сведению клиентов.
Используйте следующий код для отслеживания фактической версии библиотеки функций Python в среде выполнения:
getattr(azure.functions, '__version__', '< 1.2.1')
Системные библиотеки среды выполнения
Список предварительно установленных системных библиотек в образах Docker рабочей роли Python см. в следующих статьях:
Functions runtime (Среда выполнения функций) | Версия Debian | Версии Python |
---|---|---|
Версия 3.x | Buster | Python 3.7. Python 3.8 Python 3.9 |
Расширения для рабочей роли Python
Процесс рабочей роли Python, который выполняется в Функциях Azure, позволяет интегрировать в приложение-функцию библиотеки сторонних поставщиков. Эти библиотеки расширений выполняют роль ПО промежуточного слоя для добавления определенных операций в жизненный цикл выполнения функции.
Расширения импортируются в коде функции примерно так же, как и стандартные модули библиотек Python. Расширения выполняются на основе следующих областей:
Scope | Description |
---|---|
Уровень приложения | Если расширение импортируется в любом триггере функции, оно применяется ко всем выполнениям этой функции в приложении. |
уровень функции. | Выполнение ограничивается только тем триггером функции, в котором импортируется расширение. |
Просмотрите сведения о каждом расширении, чтобы узнать больше о области, в которой выполняется расширение.
Расширения реализуют интерфейс расширения рабочей роли Python. Это действие позволяет рабочему процессу Python вызывать код расширения во время жизненного цикла выполнения функции. Дополнительные сведения см. в статье "Создание расширений".
Применение расширений
Вы можете использовать библиотеку расширения рабочей роли Python в функциях Python, выполнив следующие действия:
- Добавьте пакет расширений в файл requirements.txt для проекта.
- Установите библиотеку в приложение.
- Добавьте следующие параметры приложения:
- Локально: введите
"PYTHON_ENABLE_WORKER_EXTENSIONS": "1"
Values
раздел файла local.settings.json. - Azure: введите
PYTHON_ENABLE_WORKER_EXTENSIONS=1
параметры приложения.
- Локально: введите
- Импортируйте модуль расширения в триггер функции.
- Настройте экземпляр расширения, если нужно. Заранее выясните требования к конфигурации, изучив документацию по расширению.
Внимание
Сторонние библиотеки рабочих расширений Python не поддерживаются и не гарантируются корпорацией Майкрософт. Необходимо убедиться, что все расширения, используемые в приложении-функции, являются надежными, и вы несете полный риск использования вредоносного или плохо написанного расширения.
Сторонние организации должны предоставить конкретную документацию по установке и использованию расширений в приложении-функции. Простой пример см. в разделе Использование расширения.
По этим ссылкам вы можете ознакомиться с применением расширений с разной областью действия в приложении-функции:
# <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
Создание расширений
Расширения создаются сторонними разработчиками библиотек, которые предоставляют функции с поддержкой интеграции в Функциях Azure. Разработчик расширения самостоятельно проектирует, реализует и публикует пакеты Python, которые содержат специализированную логику для работы в контексте выполнения функций. Эти расширения могут публиковаться через реестр PyPI или репозитории GitHub.
Дополнительные сведения о создании, упаковке, публикации и использовании пакетов расширений для рабочей роли Python см. в статье Разработка рабочих расширений Python для Функций Azure.
Расширения уровня приложения
Расширение, унаследованное от AppExtensionBase
запусков в области приложения .
AppExtensionBase
предоставляет следующие абстрактные методы класса, которые вам нужно реализовать.
Метод | Description |
---|---|
init |
Вызывается после завершения импорта расширения. |
configure |
Вызывается из кода функции, когда нужно настроить расширение. |
post_function_load_app_level |
Вызывается сразу после загрузки функции. В расширение передаются параметры с именем функции и каталогом, где она размещается. Помните, что каталог функций доступен только для чтения, и любая попытка записи в локальный файл в этом каталоге завершается ошибкой. |
pre_invocation_app_level |
Вызывается прямо перед активацией функции. В расширение передаются контекст функции и аргументы, указанные в вызове функции. Обычно вы также можете передавать другие атрибуты в объекте контекста, чтобы использовать их в коде функции. |
post_invocation_app_level |
Вызывается сразу после завершения выполнения функции. В расширение передаются контекст функции, аргументы вызова функции и возвращаемый объект вызова. Эта реализация очень удобна для проверки, успешно ли применены перехватчики жизненного цикла. |
Расширения уровня функции
Расширение, наследуемое от FuncExtensionBase, выполняется только в определенном триггере функции.
FuncExtensionBase
предоставляет следующие абстрактные методы класса, которые вам нужно реализовать.
Метод | Description |
---|---|
__init__ |
Конструктор расширения. Он вызывается при инициализации экземпляра приложения для конкретной функции. При реализации этого абстрактного метода может потребоваться принять filename параметр и передать его методу родительского объекта super().__init__(filename) для правильной регистрации расширений. |
post_function_load |
Вызывается сразу после загрузки функции. В расширение передаются параметры с именем функции и каталогом, где она размещается. Помните, что каталог функций доступен только для чтения, и любая попытка записи в локальный файл в этом каталоге завершается ошибкой. |
pre_invocation |
Вызывается прямо перед активацией функции. В расширение передаются контекст функции и аргументы, указанные в вызове функции. Обычно вы также можете передавать другие атрибуты в объекте контекста, чтобы использовать их в коде функции. |
post_invocation |
Вызывается сразу после завершения выполнения функции. В расширение передаются контекст функции, аргументы вызова функции и возвращаемый объект вызова. Эта реализация очень удобна для проверки, успешно ли применены перехватчики жизненного цикла. |
Предоставление общего доступа к ресурсам независимо от источника
Функции Azure поддерживают общий доступ к ресурсам независимо от источника (CORS). CORS настраивается на портале и через Azure CLI. Список разрешенных источников CORS применяется на уровне приложения-функции. При включении CORS ответы включают заголовок Access-Control-Allow-Origin
. Дополнительные сведения см. в статье об общем доступе к ресурсам независимо от источника.
Общий доступ к ресурсам между источниками (CORS) полностью поддерживается для приложений-функций Python.
Асинхронная
По умолчанию экземпляр узла для Python может одновременно обрабатывать только один вызов функции. Это связано с тем, что Python является однопоточной средой выполнения. Для приложения-функции, обрабатывающего большое количество событий ввода-вывода и (или) связанных с вводом-выводом, можно повысить производительность, выполняя функции асинхронно. Подробную информацию см. в статье Повышение производительности приложений Python в Функциях Azure.
Общая память (предварительная версия)
Чтобы повысить пропускную способность, Функции Azure позволяет внепроцессной рабочей роли Python делиться памятью с узлом Функций. Когда приложение-функция достигает узких мест, вы можете включить общую память, добавив параметр приложения с именем FUNCTIONS_WORKER_SHARED_MEMORY_DATA_TRANSFER_ENABLED со значением 1
. После включения общей памяти можно использовать параметр DOCKER_SHM_SIZE, чтобы задать общий объем памяти подобно 268435456
, что эквивалентно 256 МБ.
Например, можно включить общую память для уменьшения узких мест при использовании привязок хранилища BLOB-объектов для передачи полезных данных размером более 1 МБ.
Эта функция доступна только для приложений-функций, работающих в планах "Премиум" и "Выделенный" (приложение Azure служба). Дополнительные сведения см. в разделе Общая память.
Известные проблемы и часто задаваемые вопросы
Ниже приведены два руководства по устранению распространенных проблем:
Ниже приведены два руководства по устранению известных проблем с моделью программирования версии 2.
- Не удалось загрузить файл или сборку
- Не удается разрешить подключение служба хранилища Azure с именем Storage
Все известные проблемы и запросы функций отслеживаются в списке проблем GitHub. Если возникла проблема и не удается найти проблему в GitHub, откройте новую проблему и включите подробное описание проблемы.
Следующие шаги
Дополнительные сведения см. на следующих ресурсах:
- Документация по API пакета Функций Azure
- Рекомендации по функциям Azure
- Azure Functions triggers and bindings (Триггеры и привязки в Функциях Azure)
- Привязки Хранилища BLOB-объектов
- Привязки HTTP и webhook
- Привязки хранилища очередей
- Триггеры таймера
Проблемы с использованием Python? Расскажите нам, что происходит.