مشاركة عبر


تطوير ملحقات عامل Python لوظائف Azure

وظائف Azure يتيح لك دمج السلوكيات المخصصة كجزء من تنفيذ دالة بيثون. تمكنك هذه الميزة من إنشاء منطق الأعمال الذي يمكن للعملاء استخدامه بسهولة في تطبيقات الوظائف الخاصة بهم. لمعرفة المزيد، راجع Python developer reference. يتم دعم ملحقات العامل في كل من نماذج برمجة v1 وv2 Python.

ستتعلم في هذه البرنامج التعليمي كيفية:

  • إنشاء ملحق عامل Python على مستوى التطبيق لوظائف Azure.
  • استهلك الإضافة في التطبيق بالطريقة التي يستهلكها عملاؤك.
  • احزم ملحقًا للاستهلاك وانشره.

المتطلبات الأساسية

قبل البدء، يجب أن تستوفي هذه المتطلبات:

إنشاء ملحق عامل 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

  1. أنشئ مجلدًا جديدًا لمشروع التطبيق وانتقل إليه.

  2. من shell المناسبة، مثل Bash، قم بتشغيل الأمر التالي لتهيئة المشروع:

    func init --python
    
  3. استخدم الأمر التالي لإنشاء وظيفة مشغّل HTTP جديدة تسمح بالوصول المجهول:

    func new -t HttpTrigger -n HttpTrigger -a anonymous
    

تنشيط بيئة ظاهرية

  1. أنشئ بيئة Python افتراضية، استنادًا إلى نظام التشغيل كما يلي:

    python3 -m venv .venv
    
  2. قم بتنشيط بيئة Python الظاهرية، استنادًا إلى نظام التشغيل على النحو التالي:

    source .venv/bin/activate
    

تكوين الملحق

  1. قم بتثبيت الحزم البعيدة لمشروع تطبيق الوظائف باستخدام الأمر التالي:

    pip install -r requirements.txt
    
  2. قم بتثبيت الملحق من مسار الملف المحلي لديك، في وضع قابل للتحرير كما يلي:

    pip install -e <PYTHON_WORKER_EXTENSION_ROOT>
    

    في هذا المثال، استبدل <PYTHON_WORKER_EXTENSION_ROOT> بموقع الملف الجذر لمشروع الملحق الخاص بك.

    عندما يستخدم أحد العملاء الملحق، فسيضيف بدلاً من ذلك موقع حزمة الملحق إلى الملف requirements.txt، كما في الأمثلة التالية:

    # requirements.txt
    python_worker_extension_timer==1.0.0
    
  3. افتح ملف المشروع local.settings.json وأضف الحقل التالي إلى Values:

    "PYTHON_ENABLE_WORKER_EXTENSIONS": "1" 
    

    عند التشغيل في Azure، يمكنك بدلاً من ذلك إضافة PYTHON_ENABLE_WORKER_EXTENSIONS=1 إلى app settings in the function app.

  4. أضف سطرين التاليين قبل الدالة main في ملف __init.py__ لنموذج البرمجة v1، أو في ملف function_app.py لنموذج البرمجة v2:

    from python_worker_extension_timer import TimerExtension
    TimerExtension.configure(append_to_http_response=True)
    

    يستورد هذا الرمز الوحدة النمطية TimerExtension ثم يقوم بتعيين قيمة التكوين append_to_http_response.

التحقق من الملحق

  1. من مجلد جذر مشروع التطبيق، ابدأ تشغيل مضيف الوظيفة باستخدام func host start --verbose. يجب أن تشاهد نقطة النهاية المحلية لوظيفتك في الإخراج كـ https://localhost:7071/api/HttpTrigger.

  2. في المستعرض، أرسل طلب 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 أو نظام التحكم بالإصدار (VCS).

لنشر ملحقك إلى PyPI:

  1. قم بتشغيل الأمر التالي لتثبيت twine وwheel في بيئة Python الافتراضية أو بيئة ظاهرية:

    pip install twine wheel
    
  2. قم بإزالة مجلد dist/ القديم من مستودع الملحقات.

  3. قم بتشغيل الأمر التالي لإنشاء حزمة جديدة داخل dist/:

    python setup.py sdist bdist_wheel
    
  4. قم بتشغيل الأمر التالي لتحميل الحزمة إلى PyPI:

    twine upload dist/*
    

    قد تحتاج إلى توفير بيانات اعتماد حساب PyPI في أثناء التحميل. يمكنك أيضا اختبار تحميل الحزمة الخاصة بك باستخدام twine upload -r testpypi dist/*. لمزيد من المعلومات، راجع وثائق Twine.

بعد هذه الخطوات، يمكن للعملاء استخدام ملحقك عن طريق تضمين اسم الحزمة في requirements.txt الخاصة بهم.

للحصول على مزيدٍ من المعلومات، راجع البرنامج التعليمي الرسمي لتعبئة Python.

الأمثلة

  • يمكنك عرض مشروع الملحق النموذج المكتمل من هذه المقالة في مستودع نماذج python_worker_extension_timer.

  • يُعد تكامل OpenCensus مشروعًا مفتوح المصدر يستخدم واجهة الملحق لدمج تتبع بيانات تتبع الاستخدام في تطبيقات Python على وظائف Azure. راجع المستودع opencensus-python-extensions-azure لاستعراض تنفيذ ملحق عامل Python هذا.

الخطوات التالية

للحصول على مزيدٍ من المعلومات حول تطوير Python في وظائف Azure، راجع الموارد التالية: