Pythonで記述するAzure FunctionsのV2 modelを試してみる

2022/10/30に公開

はじめに

Pythonで記述するAzure FunctionsにV2 modelというものがpreviewで公開されました。
一番の変更点としては関数アプリの設定ファイルであるfunction.jsonがなくなったことです。
設定ファイルの代わりにデコレータを利用してトリガーやバインディングの設定を行うようになりました。

まずは試す

要件

V2 modelをローカルで試すには以下の要件を満たしている必要があります。
バージョンが古い、そもそもインストールしていないといった場合は要件を満たすバージョンをインストールしてください。

  • Python 3.7以降
  • Azure Functions Core Toolsのバージョン4.0.4785以降
  • Azuriteのインストール

以下、今回試した私の環境です。

  • Python == 3.9
  • Azure Functions Core Tools == 4.0.4785
  • Azurite == 3.17.1
  • Windows 10 Pro

プロジェクトの作成

以下のコマンドでAzure Functionsのプロジェクトを作成します。

func init azure-functions-test --python -m V2

azure-functions-testというディレクトリが作成されているので移動します。

cd azure-functions-test

Pythonの仮想環境を作成し、Pythonを仮想環境の物に切り替えます。
プロジェクトごとにPythonの環境を分けるために仮想環境を作成しています。仮想環境なんていらないという場合はこの項目はスキップで大丈夫です。

python -m venv .venv
.venv\Scripts\activate

実行に必要なモジュールをインストールします。

pip install -r requirements.txt

実行してみる

これまでの作業でプロジェクトの作成が完了したので、実際に関数アプリを動かしてみます。

別のターミナルを立ち上げ、以下のコマンドでAzuriteを起動します。

azurite

以下のコマンドで関数アプリを起動します。

func start

起動が完了するとターミナルにURLが表示されるのでブラウザでアクセスしてみましょう。
http://localhost:7071/api/hello

HttpTrigger1 function processed a request!!!

というメッセージが表示されていればOKです。

コードを見てみる

動くことは確かめたので次はコードを見てみます。

関数アプリの本体はfunction_app.pyに記述されています。
今のところ関数を記述するファイル名はfunction_app.pyである必要があるそうです。

お好きなエディターでfunction_app.pyを開きましょう。
ちなみに、私はVSCodeを使っています。

function_app.py
import azure.functions as func

app = func.FunctionApp()

@app.function_name(name="HttpTrigger1")
@app.route(route="hello") # HTTP Trigger
def test_function(req: func.HttpRequest) -> func.HttpResponse:
    return func.HttpResponse("HttpTrigger1 function processed a request!!!")

ぱっと見た感じFlaskやFastAPIっぽい見た目ですね。
親しみのある人も多いんじゃないでしょうか。

それではデコレータを見てみます。
5行目の@app.function_name(name="HttpTrigger1")は関数の名前を設定しています。
このデコレータは無くても動きます。
デコレータがない場合の関数の名前はPythonコード上で定義している関数の名前になります。今回の場合はtest_functionです。

6行目の@app.route(route="hello")はこの関数がHTTP Triggerであることを設定しています。
HTTP Triggerとして関数を定義したい場合はこのデコレータが必要になります。
引数のroute="hello"はエンドポイント名を設定しています。この引数が省略されていた場合は関数の名前(HttpTrigger1)がエンドポイントとなります。さらに、関数の名前が設定されていない場合はPythonコード上で定義されている関数の名前(test_function)がエンドポイントとなります。

関数を追加してみる

関数を追加してみます。
今までは設定ファイルであるfunction.jsonが必要だった関係なのか1関数1フォルダという感じになっていましたが、function.jsonが不要になったことで1つのファイルに複数の関数を定義できるようになっています。

function_app.py
# ~ 省略 ~
@app.function_name(name="HttpTrigger2")
@app.route(route="hoge")
def test_function2(req: func.HttpRequest) -> func.HttpResponse:
    return func.HttpResponse("新しい関数を追加したよ!!")

test_function2を定義しました。
関数名はHttpTrigger2とし、エンドポイントはhogeです。
ブラウザでhttp://localhost:7071/api/hogeにアクセスしてみましょう。

新しい関数を追加したよ!!

と表示されれば関数の追加は成功です。🎉🎉

ブループリントを使ってみる

え?関数は全部同じファイルに書かないといけないの?と思った方もいると思います。
大丈夫です。そんなあなたのためにブループリント機能があります。

まずは関数を記述するためのファイルを作成します。
今回はfunction_app2.pyというファイル名を作りますが、このファイルの名前ななんでも大丈夫です。
function_app2.pyを開き、以下のコードを書きます。

function_app2.py
import azure.functions as func

bp = func.Blueprint()

@bp.function_name('HttpTrigger3')
@bp.route(route='blueprint')
def blueprint_function(req: func.HttpRequest) -> func.HttpResponse:
    return func.HttpResponse("Blueprintで定義された関数だよ")

ブループリントを利用して関数を定義する場合は、Blueprintクラスをインスタンス化する必要があります。
それ以外は同様にして関数を定義できます。
今回はblueprint_functionを定義しました。
関数名はHttpTrigger3とし、エンドポイントはblueprintです。
ブラウザでhttp://localhost:7071/api/blueprintにアクセスしてみましょう、と行きたいところですがこのままではアクセスできません。
インスタンス化させたBlueprintをFunctionAppに読み込ませる必要があります。

function_app.pyを開き、コードを以下に置き換えます。

function_app.py
import azure.functions as func
from function_app2 import bp

app = func.FunctionApp()
app.register_blueprint(bp)

@app.function_name(name="HttpTrigger1")
@app.route(route="hello") # HTTP Trigger
def test_function(req: func.HttpRequest) -> func.HttpResponse:
    return func.HttpResponse("HttpTrigger1 function processed a request!!!")

@app.function_name(name="HttpTrigger2")
@app.route(route="hoge",)
def test_function2(req: func.HttpRequest) -> func.HttpResponse:
    return func.HttpResponse("新しい関数を追加したよ!!")

2行目のfrom function_app2 import bpでBlueprintをインポートし、5行目のapp.register_blueprint(bp)でブループリントの登録を行っています。
これで定義した関数にアクセスすることができます。

ブラウザでhttp://localhost:7071/api/blueprintにアクセスしてみましょう。

Blueprintで定義された関数だよ

と表示されればブループリントを利用した関数の定義に成功しています。🎉🎉

おわりに

PythonでのAzure Functionsの新しい記述法であるV2 modelを軽く試してみました。
設定ファイルが不要になったことにより、ディレクトリの構造は自由度が増したように感じます。個人的には以前の1関数1フォルダはディレクトリ構造を考える必要がなく楽だったので名残惜しくはありますが。
新しい記述法については全体的にFlaskに似ていることもあり、特に混乱することはなさそうです。
今回は試していませんが、Azure Functionsには他にも様々なトリガーがあるので、自分が使いそうなトリガーはそのうち試してみたいと思います。

参考

Python V2 model Azure Functions triggers and bindings (preview)
Azure Functions Python developer guide

Discussion