Azure Functions に２つのPython関数をデプロイする（プログラミングモデルv2の場合）

# はじめに

この記事はAzure Functionsに複数関数をPythonのプログラミングモデルv2で実装するための記事です。
[公式サイト](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-reference-python?tabs=asgi%2Capplication-level&pivots=python-mode-decorators "Azure Functions の Python 開発者向けガイド")にはHttpトリガーの例だけ記載があるようなので、Timer Triggerではどうなるか試してみました。

# 前提
[以前書いた記事](https://qiita.com/fsd-takizawa/items/bece94313b4c256c0a81)の環境準備ができていることが前提になります。
（Azure Functionsのランタイムは4.x、Pythonのバージョンは3.10）
また[以前書いた記事](https://qiita.com/fsd-takizawa/items/bece94313b4c256c0a81)で作成したプロジェクトを修正して実装しますので、すでにTimer Triggerの関数プロジェクトが作成されてるものとして進めます。

# 共通関数の実装

複数関数を定義する場合多くの場合は共通関数が必要になると思いますので、今回共通クラスを定義してそれぞれトリガーされる関数から呼び出します。

1. プロジェクトにフォルダ`common_func`を作成し、作成したフォルダ内に`__init__.py`ファイルを作成します。
1. 同じフォルダに`commom.py`ファイルを作成します。
    ```py:commom.py
    import logging

    class CommonTest:
        def outputStr(self) -> None:
            logging.info("共通処理が呼び出されました。")
    ```

# トリガー関数の実装

1. プロジェクト直下にフォルダ`main_func`を作成して、作成したフォルダに`__init__.py`と`timer_blueprint1.py`、`timer_blueprint2.py`を作成します。
1. `timer_blueprint1.py`、`timer_blueprint2.py`を実装します。
    ```py:timer_blueprint1.py
    import datetime
    import logging
    
    import azure.functions as func 
    from common_func.common import CommonTest
    
    bp1 = func.Blueprint()
    bp1.function_name("timer_trigger1")
    
    @bp1.schedule(schedule="0 */5 * * * *", arg_name="myTimer1", run_on_startup=False,
                  use_monitor=False)
    def timer_trigger1(myTimer1: func.TimerRequest) -> None:
        utc_timestamp = datetime.datetime.utcnow().replace(
        tzinfo=datetime.timezone.utc).isoformat()
    
        if myTimer1.past_due:
            logging.info('The timer is past due!')
    
        logging.info('timer_trigger1 が起動されました at %s', utc_timestamp)
        
        clazz = CommonTest()
        clazz.outputStr()
    
    ```
    ```py:timer_blueprint2.py
    import datetime
    import logging
    
    import azure.functions as func 
    from common_func.common import CommonTest
    
    bp2 = func.Blueprint()
    bp2.function_name("timer_trigger2")
    
    @bp2.schedule(schedule="0 */5 * * * *", arg_name="myTimer2", run_on_startup=False,
                  use_monitor=False)
    def timer_trigger2(myTimer2: func.TimerRequest) -> None:
        utc_timestamp = datetime.datetime.utcnow().replace(
        tzinfo=datetime.timezone.utc).isoformat()
    
        if myTimer2.past_due:
            logging.info('The timer is past due!')
    
        logging.info('timer_trigger2 が起動されました at %s', utc_timestamp)
        
        clazz = CommonTest()
        clazz.outputStr()
    
    ```

    スケジュールの定義は`func.Blueprint()`で記述します。`@bp2.schedule(…)`の…部分の設定方法は1関数の時のデコレーションと同じです。

# function_app.py の修正

`function_app.py`を次のように修正します。

```py:function_app.py
import azure.functions as func

from main_func.timer_blueprint1 import bp1
from main_func.timer_blueprint2 import bp2

app = func.FunctionApp()

app.register_functions(bp1)
app.register_functions(bp2)
```
エントリポイントは`function_app.py`ファイル内のみにあるため、`function_app.py`ファイルでブループリントオブジェクトをインポートして、そのオブジェクトを関数アプリに登録します。

# 最後に

v1の場合は単純に関数を追加で増やせばよいですが、v2はBlueprintsを利用して実現します。
v1の方が単純で簡単ですが、いずれv2が主流になってくると思いますので、どちらでも実装できるようにしておきたいですね。

# 参考資料

[Azure Functions の Python 開発者向けガイド](https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-reference-python?tabs=asgi%2Capplication-level&pivots=python-mode-decorators "Azure Functions の Python 開発者向けガイド")