Pythonで記述するAzure FunctionsのV2 modelを試してみる
はじめに
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を使っています。
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つのファイルに複数の関数を定義できるようになっています。
# ~ 省略 ~
@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
を開き、以下のコードを書きます。
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
を開き、コードを以下に置き換えます。
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