Flask
Flaskは、Armin Ronacherによって開発されたオープンソースライセンス(BSDライセンス)のフレームワークです。テンプレートエンジンとしてJinja2、WSGIツールキットとしてWerkzeug(ヴェルクツォイク)を利用しています。
- Jinja2: Pythonで利用できるHTMLテンプレートエンジン
- Werkzeug: WSGIアプリケーションのためのユーティリティを集めたライブラリ
データベースの抽象化など、必要に応じて拡張(Extension)を行う軽量なフレームワークです。
・Flask - Getting Started
実際にFlaskを動かしてみましょう。以下のコマンドを実行して、Flaskをインストールします。
1 | $ python -m pip install Flask |
次のように
hello.py
ファイルを作成します。
01 | from flask import Flask, Response |
09 | @app.route('/hello/<name>') |
11 | response = Response('Hello, '+ name) |
12 | response.mimetype = 'text/plain' |
13 | return response</name> |
Flaskのサーバを起動します。
1 | $ export FLASK_APP=hello.py #起動するアプリをFlaskに伝える |
2 | $ export FLASK_ENV=development #サーバーを開発モードに設定 |
4 | * Serving Flask app 'hello' (lazy loading) |
5 | * Environment: production |
6 | WARNING: This is a development server. Do not use it in a production deployment. |
7 | Use a production WSGI server instead. |
http://127.0.0.1:5000/hello
にアクセスします。
・Flaskプロジェクトのレイアウト
Flaskではディレクトリ構造などが特に定められているわけではありませんが、プロジェクト内に以下のようなディレクトリを持つことがプラクティスとされています。
flaskr/
: アプリケーションのコードとファイルを含んだPythonパッケージ
tests/
: テストモジュールを含んだディレクトリ
venv/
: Flaskとその他の依存対象がインストールされたPythonの仮想環境
- その他のファイル: インストールなどに利用
・Flaskアプリケーションのルーティング
Flaskでは、Route()デコレータを使用して関数とURLを関連付けできます。変数を扱いたい場合には< >
を利用します。デコレータとは、関数やクラスにフレームワークの機能などを付加するための修飾子です。
・FlaskアプリケーションのHTTPメソッド
HTTPメソッドの記述も、Route()デコレータ内で行います。
1 | @app.route('/book/json', methods=['GET']) |
3 | book = Book('example title', 'example author') |
4 | return jsonify(book.__dict__) |
・Flaskで簡単なAPIを作成
実際にAPIを作成してみます。FlaskはDjangoよりもAPIに特化したフレームワークのため、簡単に実装できます。返却する値としてJSONを利用したいため、Extensionを追加してJSONレスポンスを取得するAPIを作成します。
hello.py
という名前のファイルを作成し、中身を以下のようにします。
01 | from flask import Flask, Response, jsonify |
04 | def __init__(self, title, author): |
14 | @app.route('/hello/<name>') |
16 | response = Response('Hello, '+ name) |
17 | response.mimetype = 'text/plain' |
20 | @app.route('/book/json', methods=['GET']) |
22 | book = Book('example title', 'example author') |
23 | return jsonify(book.__dict__)</name> |
先述の
flask run
コマンドを利用し、サーバを起動します。
1 | $ export FLASK_APP=hello.py #起動するアプリをFlaskに伝える |
2 | $ export FLASK_ENV=development #サーバーを開発モードに設定 |
別のターミナルから
curl
を実行します。
3 | "author": "example author", |
4 | "title": "example title" |
FastAPI
FastAPIは@tiangolo(Sebastián Ramírez)によって開発された、Python 3.6以降でAPIを構築するためのオープンソース(MIT)・Webフレームワークです。REST APIの実装に特化しており、OpenAPIに準拠しています。自動でAPIドキュメントを生成する機能があり、Flaskのようにプラグインによる拡張も可能です。Starlette/Uvicorn/Pydanticをベースにしたフレームワークで、以下を担う構造です。
- Starlette/Uvicorn: Web部分(ASGI Server)
- Pydantic: データ部分(Validation/Serialization)
・FastAPI - Getting Started
実際にFastAPIを動かしてみましょう。以下のコマンドを実行して、FastAPIをインストールします。
1 | $ python -m pip install fastapi |
以下のように
hello.py
ファイルを作成します。
1 | from fastapi import FastAPI |
7 | return {'hello':'world'} |
アプリケーションの実行のためにASGIサーバ(ASGIについては先述)のインストールが必要です。Uvicornをインストールします。
1 | $ python -m pip install "uvicorn[standard]" |
Uvicornを起動します。
1 | $ uvicorn hello:app --reload |
2 | INFO: Will watch for changes in these directories: ['/home/opc/develop/python/fastapi'] |
4 | INFO: Started reloader process [13722] using watchgod |
5 | INFO: Started server process [13724] |
6 | INFO: Waiting for application startup. |
7 | INFO: Application startup complete. |
curlコマンドを実行します。
・FastAPIアプリケーションのHTTPメソッド
FastAPIのHTTPメソッド指定はFlaskとは若干異なり、それぞれのデコレータが用意されています。
5 | async def post_item(item: Item): |
・FastAPIアプリケーションのルーティング
関数とパスを関連付ける形でアプリケーションのルーティングを行います。
3 | return {'hello':'world'} |
パスパラメータを利用できます。
1 | @app.get('/items/{item_id}') |
2 | def get_item(item_id: int, q: str = None): |
3 | return {'item_id': item_id, 'q': q} |
クエリパラメータを(`?item_id=1000`のように)渡すことも可能です。
2 | async def get_item(item_id: int = 0): |
3 | return {'item_id': item_id} |
・FastAPIの自動ドキュメント生成
[endpoint]/docs
にアクセスすると、自動生成された Swagger UIにアクセスできます。
・FastAPIで簡単なAPIを作成
ここまでのサンプルコードをhello.py
に記述します。
01 | from fastapi import FastAPI |
07 | return {'hello':'world'} |
09 | @app.get('/items/{item_id}') |
10 | def get_item(item_id: int, q: str = None): |
11 | return {'item_id': item_id, 'q': q} |
14 | async def get_item(item_id: int = 0): |
15 | return {'item_id': item_id} |
17 | from pydantic import BaseModel |
23 | async def post_item(item: Item): |
ASGIサーバを起動します。
別のターミナルからAPIを実行してみます。
09 | > -H 'accept: application/json' \ |
10 | > -H 'Content-Type: application/json' \ |