Разработка расширений рабочих ролей Python для Функций Azure
Функции Azure позволяют интегрировать пользовательские поведения в рамках выполнения функции Python. Эта функция позволяет создавать бизнес-логику, которую клиенты могут легко использовать в своих собственных приложениях-функциях. Дополнительные сведения см. в разделе Справочник разработчика Python. Расширения рабочих ролей поддерживаются в моделях программирования Python версии 1 и 2.
Из этого руководства вы узнаете, как выполнять следующие задачи:
- Создание расширения рабочей роли Python на уровне приложения для Функций Azure.
- Используйте свое расширение в приложении так же, как это делают ваши клиенты.
- Упакуйте и опубликуйте расширение для использования.
Предварительные требования
Перед началом работы необходимо выполнить следующие условия:
Python 3.7 или более поздней версии. Полный список поддерживаемых версий Python в службе "Функции Azure" см. в руководстве разработчика Python.
Функции Azure Core Tools версии 4.0.5095 или более поздней, которая поддерживает использование расширения с моделью программирования Python версии 2. Проверьте версию с помощью
func --version
.Приложение Visual Studio Code, установленное на одной из поддерживаемых платформ.
Создание расширения рабочей роли Python
Создаваемое расширение сообщает о времени, затраченном на вызов триггера HTTP в журналах консоли и в тексте HTTP-отклика.
Структура папок
Папка проекта расширения должна иметь следующую структуру:
<python_worker_extension_root>/
| - .venv/
| - python_worker_extension_timer/
| | - __init__.py
| - setup.py
| - readme.md
Папка/файл | Описание |
---|---|
.venv/ | (Дополнительно) Содержит виртуальную среду Python, используемую для локальной разработки. |
python_worker_extension/ | Содержит исходный код расширения рабочей роли Python. Эта папка содержит основной модуль Python, который будет опубликован в PyPI. |
setup.py | Содержит метаданные пакета расширения рабочей роли Python. |
readme.md | Содержит инструкции и использование расширения. Это содержимое отображается как описание на домашней странице в проекте PyPI. |
Настройка метаданных проекта
Сначала создайте setup.py
, который предоставляет ценные сведения о пакете. Чтобы обеспечить корректное распространение и интеграцию расширения в приложения-функции клиента, убедитесь в том, что 'azure-functions >= 1.7.0, < 2.0.0'
находится в разделе install_requires
.
В следующем разделе при необходимости измените поля author
, author_email
, install_requires
, license
, packages
и url
.
from setuptools import find_packages, setup
setup(
name='python-worker-extension-timer',
version='1.0.0',
author='Your Name Here',
author_email='your@email.here',
classifiers=[
'Intended Audience :: End Users/Desktop',
'Development Status :: 5 - Production/Stable',
'Intended Audience :: End Users/Desktop',
'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
],
description='Python Worker Extension Demo',
include_package_data=True,
long_description=open('readme.md').read(),
install_requires=[
'azure-functions >= 1.7.0, < 2.0.0',
# Any additional packages that will be used in your extension
],
extras_require={},
license='MIT',
packages=find_packages(where='.'),
url='https://your-github-or-pypi-link',
zip_safe=False,
)
Далее необходимо реализовать код расширения в области уровня приложения.
Реализация расширения таймера
Добавьте следующий код в python_worker_extension_timer/__init__.py
, чтобы реализовать расширение уровня приложения:
import typing
from logging import Logger
from time import time
from azure.functions import AppExtensionBase, Context, HttpResponse
class TimerExtension(AppExtensionBase):
"""A Python worker extension to record elapsed time in a function invocation
"""
@classmethod
def init(cls):
# This records the starttime of each function
cls.start_timestamps: typing.Dict[str, float] = {}
@classmethod
def configure(cls, *args, append_to_http_response:bool=False, **kwargs):
# Customer can use TimerExtension.configure(append_to_http_response=)
# to decide whether the elapsed time should be shown in HTTP response
cls.append_to_http_response = append_to_http_response
@classmethod
def pre_invocation_app_level(
cls, logger: Logger, context: Context,
func_args: typing.Dict[str, object],
*args, **kwargs
) -> None:
logger.info(f'Recording start time of {context.function_name}')
cls.start_timestamps[context.invocation_id] = time()
@classmethod
def post_invocation_app_level(
cls, logger: Logger, context: Context,
func_args: typing.Dict[str, object],
func_ret: typing.Optional[object],
*args, **kwargs
) -> None:
if context.invocation_id in cls.start_timestamps:
# Get the start_time of the invocation
start_time: float = cls.start_timestamps.pop(context.invocation_id)
end_time: float = time()
# Calculate the elapsed time
elapsed_time = end_time - start_time
logger.info(f'Time taken to execute {context.function_name} is {elapsed_time} sec')
# Append the elapsed time to the end of HTTP response
# if the append_to_http_response is set to True
if cls.append_to_http_response and isinstance(func_ret, HttpResponse):
func_ret._HttpResponse__body += f' (TimeElapsed: {elapsed_time} sec)'.encode()
Этот код наследует от AppExtensionBase, чтобы применять расширение к каждой функции в приложении. Расширение можно также реализовать в области на уровне функции, наследуя от FuncExtensionBase.
Метод init
— это метод класса, который вызывается рабочей ролью при импорте класса расширения. Здесь можно выполнить действия по инициализации расширения. В этом случае инициализируется сопоставление хэша для записи времени начала вызова для каждой функции.
Метод configure
ориентирован на клиента. В файле Readme можно сообщить клиентам о необходимости вызова Extension.configure()
. В файле Readme также должны быть документированы возможности расширения, доступная конфигурация и область применения вашего расширения. В этом примере клиенты могут выбрать, будет ли затраченное время указано в HttpResponse
.
Метод pre_invocation_app_level
вызывается рабочей ролью Python перед выполнением функции. Он предоставляет сведения из функции, такие как контекст функции и аргументы. В этом примере расширение записывает в журнал сообщение и записывает время начала вызова на основе его идентификатора invocation_id.
Аналогичным образом метод post_invocation_app_level
вызывается после выполнения функции. В этом примере затраченное время рассчитывается по времени начала и текущему времени. Кроме того, возвращаемое значение HTTP-отклика перезаписывается.
Создание readme.md
Создайте файл readme.md в корне проекта расширения. Этот файл содержит инструкции и сведения об использовании расширения. Содержимое readme.md отображается в качестве описания на домашней странице проекта PyPI.
# Python Worker Extension Timer
In this file, tell your customers when they need to call `Extension.configure()`.
The readme should also document the extension capabilities, possible configuration,
and usage of your extension.
Локальное использование расширения
Созданное расширение можно использовать в проекте приложения, чтобы убедиться в том, что оно работает должным образом.
Создание функции для триггеров HTTP
Создайте новую папку для проекта приложения и перейдите к ней.
В соответствующей оболочке, например bash, выполните следующую команду, чтобы инициализировать проект:
func init --python
Используйте следующую команду, чтобы создать новую функцию триггера HTTP, которая разрешает анонимный доступ.
func new -t HttpTrigger -n HttpTrigger -a anonymous
Активация виртуальной среды
Создайте виртуальную среду Python на основе ОС следующим образом.
Активируйте виртуальную среду Python на основе ОС следующим образом.
Настройка расширения
Установите удаленные пакеты для проекта приложения-функции с помощью следующей команды:
pip install -r requirements.txt
Установите расширение из локального пути к файлу в режиме редактирования.
pip install -e <PYTHON_WORKER_EXTENSION_ROOT>
В этом примере замените
<PYTHON_WORKER_EXTENSION_ROOT>
корневым расположением файла проекта расширения.Когда клиент использует ваше расширение, он добавляет расположение пакета расширения в файл requirements.txt, как показано в следующих примерах.
Откройте файл проекта local.settings.json и добавьте следующее поле в
Values
."PYTHON_ENABLE_WORKER_EXTENSIONS": "1"
При запуске в Azure необходимо вместо этого добавить
PYTHON_ENABLE_WORKER_EXTENSIONS=1
в параметры приложения в приложении-функции.Добавьте следующие две строки перед
main
функцией в файле __init.py__ для модели программирования версии 1 или в файле function_app.py для модели программирования версии 2:from python_worker_extension_timer import TimerExtension TimerExtension.configure(append_to_http_response=True)
Этот код импортирует модуль
TimerExtension
и задает значение конфигурацииappend_to_http_response
.
Проверка расширения
В корневой папке проекта приложения запустите узел функции с помощью
func host start --verbose
. Локальная конечная точка функции должна отображаться в выходных данных какhttps://localhost:7071/api/HttpTrigger
.В браузере отправьте запрос GET в
https://localhost:7071/api/HttpTrigger
. Должен отобразиться примерно такой отклик, как указано ниже, с добавленными данными TimeElapsed для запроса.This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response. (TimeElapsed: 0.0009996891021728516 sec)
Публикация расширения
После создания и проверки расширения вам в любом случае потребуется выполнить оставшиеся задачи публикации.
- Выберите лицензию.
- Создайте файл readme.md и другую документацию.
- Опубликуйте библиотеку расширений в реестре пакетов Python или в системе управления версиями.
Чтобы опубликовать расширение в PyPI, выполните следующие действия.
Выполните следующую команду, чтобы установить
twine
иwheel
в среде Python по умолчанию или в виртуальной среде.pip install twine wheel
Удалите старую папку
dist/
из репозитория расширений.Выполните следующую команду, чтобы создать новый пакет в
dist/
.python setup.py sdist bdist_wheel
Выполните следующую команду, чтобы отправить пакет в PyPI.
twine upload dist/*
Во время отправки может потребоваться указать данные учетной записи PyPI. Вы также можете протестировать отправку пакета с помощью
twine upload -r testpypi dist/*
. Дополнительные сведения см. в документации по Twine.
После выполнения этих действий клиенты смогут использовать расширение, включив имя вашего пакета в свой файл requirements.txt.
Дополнительные сведения см. в официальном руководстве по созданию пакетов Python.
Примеры
Готовый пример проекта расширения можно просмотреть в этой статье в примере репозитория python_worker_extension_timer.
Интеграция OpenCensus — это проект с открытым кодом, использующий интерфейс расширения для интеграции инструментов трассировки телеметрии в приложения Python для Функций Azure. Сведения о реализации этого расширения рабочей роли Python см. в репозитории opencensus-python-extensions-azure.
Дальнейшие действия
Дополнительные сведения о разработках под Python в рамках службы "Функции Azure" см. в статьях ниже.
- Azure Functions Python Developer Guide (Справочник по Функциям Azure для разработчика Python)
- Рекомендации по функциям Azure
- Справочник разработчика по функциям Azure