Mengembangkan ekstensi pekerja Python untuk Azure Functions

Nota

Dimulai dengan Python 3.13, ekstensi pekerja python tidak akan lagi didukung.

Azure Functions memungkinkan Anda mengintegrasikan perilaku kustom sebagai bagian dari eksekusi fungsi Python. Fitur ini memungkinkan Anda membuat logika bisnis yang dapat dengan mudah digunakan pelanggan di aplikasi fungsi mereka sendiri. Ekstensi pekerja didukung dalam kedua model pemrograman Python v1 dan v2.

Dalam tutorial ini, Anda akan mempelajari cara:

  • Buat ekstensi pekerja Python tingkat aplikasi untuk Azure Functions.
  • Gunakan ekstensi Anda dalam aplikasi dengan cara yang dilakukan oleh pelanggan Anda.
  • Mengemas dan menerbitkan ekstensi untuk digunakan.

Prasyarat

Sebelum memulai, Anda harus memenuhi persyaratan ini:

Membuat ekstensi Python Worker

Ekstensi yang Anda buat melaporkan waktu yang berlalu dari pemanggilan pemicu HTTP di log konsol dan di isi respons HTTP.

Struktur folder

Folder untuk proyek ekstensi Anda harus seperti struktur berikut:

<python_worker_extension_root>/
 | - .venv/
 | - python_worker_extension_timer/
 | | - __init__.py
 | - setup.py
 | - readme.md
Folder/berkas Description
.venv/ (Opsional) Berisi lingkungan virtual Python yang digunakan untuk pengembangan lokal.
python_worker_extension/ Berisi kode sumber ekstensi pekerja Python. Folder ini berisi modul Python utama yang akan diterbitkan ke PyPI.
setup.py Mengandung metadata paket ekstensi pekerja Python.
readme.md Berisi instruksi dan penggunaan ekstensi Anda. Konten ini ditampilkan sebagai deskripsi di halaman beranda di proyek PyPI Anda.

Mengonfigurasi metadata proyek

Pertama Anda membuat setup.py, yang menyediakan informasi penting tentang paket Anda. Untuk memastikan bahwa ekstensi Anda didistribusikan dan diintegrasikan ke dalam aplikasi fungsi pelanggan Anda dengan benar, konfirmasikan bahwa 'azure-functions >= 1.7.0, < 2.0.0' ada di bagian install_requires tersebut.

Dalam templat berikut, Anda harus mengubah bidang author, author_email, install_requires, license, packages, dan url sesuai kebutuhan.

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

Selanjutnya, Anda akan menerapkan kode ekstensi dalam cakupan tingkat aplikasi.

Menerapkan ekstensi timer

Tambahkan kode berikut di python_worker_extension_timer/__init__.py untuk mengimplementasikan ekstensi tingkat aplikasi.

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

Kode ini mewarisi dari AppExtensionBase sehingga ekstensi berlaku untuk setiap fungsi di aplikasi. Anda bisa saja menerapkan ekstensi pada cakupan tingkat fungsi dengan cara mewarisi dari FuncExtensionBase.

Metode init adalah metode kelas yang dipanggil oleh worker ketika kelas ekstensi diimpor. Anda dapat melakukan tindakan inisialisasi di sini untuk ekstensi. Dalam hal ini, peta hash diinisialisasi untuk merekam waktu mulai pemanggilan untuk setiap fungsi.

Metode configure ini berorientasi pada pelanggan. Dalam file readme Anda, Anda dapat memberi tahu pelanggan Anda kapan mereka perlu memanggil Extension.configure(). Readme juga harus mendokumentasikan kemampuan ekstensi, kemungkinan konfigurasi, dan penggunaan ekstensi Anda. Dalam contoh ini, pelanggan dapat memilih apakah waktu yang berlalu dilaporkan dalam HttpResponse.

Metode pre_invocation_app_level ini dipanggil oleh pekerja Python sebelum fungsi berjalan. Ini menyediakan informasi dari fungsi, seperti konteks fungsi dan argumen. Dalam contoh ini, ekstensi mencatat pesan dan merekam waktu mulai pemanggilan berdasarkan invocation_id.

Demikian pula, post_invocation_app_level dipanggil setelah eksekusi fungsi. Contoh ini menghitung waktu yang berlalu berdasarkan waktu mulai dan waktu saat ini. Ini juga menimpa nilai pengembalian respons HTTP.

Buat readme.md

Buat file readme.md di akar proyek ekstensi Anda. File ini berisi instruksi dan penggunaan ekstensi Anda. Konten readme.md ditampilkan sebagai deskripsi di beranda di proyek PyPI Anda.

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

Gunakan ekstensi Anda secara lokal

Setelah membuat ekstensi, Anda dapat menggunakannya dalam proyek aplikasi untuk memverifikasi bahwa ekstensi berfungsi seperti yang dimaksudkan.

Membuat fungsi pemicu HTTP

  1. Buat folder baru untuk proyek aplikasi Anda dan navigasikan ke folder tersebut.

  2. Dari shell yang sesuai, seperti Bash, jalankan perintah berikut untuk menginisialisasi proyek:

    func init --python
    
  3. Gunakan perintah berikut untuk membuat fungsi pemicu HTTP baru yang memungkinkan akses anonim:

    func new -t HttpTrigger -n HttpTrigger -a anonymous
    

Mengaktifkan lingkungan virtual

  1. Buat lingkungan virtual Python, berdasarkan OS sebagai berikut:

    python3 -m venv .venv
    
  2. Aktifkan lingkungan virtual Python, berdasarkan OS sebagai berikut:

    source .venv/bin/activate
    

Konfigurasikan ekstensi

  1. Instal paket jarak jauh untuk proyek aplikasi fungsi Anda menggunakan perintah berikut:

    pip install -r requirements.txt
    
  2. Instal ekstensi dari jalur file lokal Anda, dalam mode yang dapat diedit sebagai berikut:

    pip install -e <PYTHON_WORKER_EXTENSION_ROOT>
    

    Dalam contoh ini, ganti <PYTHON_WORKER_EXTENSION_ROOT> dengan lokasi file akar proyek ekstensi Anda.

    Saat pelanggan menggunakan ekstensi Anda, mereka akan menambahkan lokasi paket ekstensi Anda ke file requirements.txt, seperti dalam contoh berikut:

    # requirements.txt
    python_worker_extension_timer==1.0.0
    
  3. Buka file proyek local.settings.json dan tambahkan bidang berikut ke Values:

    "PYTHON_ENABLE_WORKER_EXTENSIONS": "1" 
    

    Saat dijalankan di Azure, Anda cukup menambahkan PYTHON_ENABLE_WORKER_EXTENSIONS=1 ke pengaturan aplikasi di fungsi aplikasi.

  4. Tambahkan dua baris berikut sebelum main fungsi dalam file __init.py__ untuk model pemrograman v1, atau dalam file function_app.py untuk model pemrograman v2:

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

    Kode ini mengimpor TimerExtension modul dan mengatur append_to_http_response nilai konfigurasi.

Memverifikasi ekstensi

  1. Dari folder akar proyek aplikasi Anda, jalankan host fungsi dengan menggunakan func host start --verbose. Anda akan melihat titik akhir lokal fungsi Anda dalam output sebagai https://localhost:7071/api/HttpTrigger.

  2. Di browser, kirim permintaan GET ke https://localhost:7071/api/HttpTrigger. Anda akan melihat respons seperti berikut, dengan data TimeElapsed untuk permintaan ditambahkan.

    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)
    

Menerbitkan ekstensi Anda

Setelah membuat dan memverifikasi ekstensi, Anda masih perlu menyelesaikan tugas penerbitan yang tersisa ini:

  • Pilih lisensi.
  • Buat readme.md dan dokumentasi lainnya.
  • Terbitkan pustaka ekstensi ke registri paket Python atau sistem kontrol versi (VCS).

Untuk menerbitkan ekstensi Anda ke PyPI:

  1. Jalankan perintah berikut untuk menginstal twine dan wheel di lingkungan Python default Anda atau lingkungan virtual:

    pip install twine wheel
    
  2. Hapus folder lama dist/ dari repositori ekstensi Anda.

  3. Jalankan perintah berikut untuk menghasilkan paket baru di dalam dist/:

    python setup.py sdist bdist_wheel
    
  4. Jalankan perintah berikut untuk mengunggah paket ke PyPI:

    twine upload dist/*
    

    Anda mungkin perlu memberikan kredensial akun PyPI Anda selama unggahan. Anda juga dapat menguji unggahan paket Anda dengan twine upload -r testpypi dist/*. Untuk informasi selengkapnya, lihat dokumentasi Twine.

Setelah langkah-langkah ini, pelanggan dapat menggunakan ekstensi Anda dengan menyertakan nama paket Anda di requirements.txtmereka.

Untuk informasi selengkapnya, lihat tutorial pengemasan Python resmi.

Examples

  • Anda dapat melihat proyek ekstensi sampel yang telah selesai dari artikel ini di repositori sampel python_worker_extension_timer .

  • Integrasi OpenCensus adalah proyek sumber terbuka yang menggunakan antarmuka ekstensi untuk mengintegrasikan pelacakan telemetri di aplikasi Azure Functions Python. Lihat repositori opencensus-python-extensions-azure untuk meninjau implementasi ekstensi pekerja Python ini.

Langkah selanjutnya

Untuk informasi selengkapnya tentang pengembangan Azure Functions Phyton, lihat referensi berikut ini: