Flaskが1.0になったので変更点や追加機能を雑にまとめていきます。全貌をちゃんと見たい人は、リリースノートや関連するプルリクを見てもらえればと思います。リリースノートの #から始まる数字のリンク
が対応するプルリクへのリンクになっています。
Flask Changelog — Flask 1.0.2 documentation
この記事では以下について雑に触れます。
- flask run コマンドの変更
- flask routes コマンドの追加
- HTTPExceptionのエラーハンドリングの変更
- Flask.loggerに関する変更
- ResponseオブジェクトのJSONサポート
flask run コマンドの変更
Flaskアプリケーションは、flask run
というコマンドでアプリケーションを実行できます。バージョン1.0になり、コマンドにいくつかの変更が加えられました。
python-dotenvとの連携
python-dotenv がインストールされていると、flask run
や Flask.run()
実行時に .env
もしくは .flaskenv
を自動的に読み込んでくれるようになりました。
ファイル | 内容 |
---|---|
.env | APIキーなどの機密情報を含める。リポジトリにはコミットしない。 |
.flaskenv | 公開しても問題ない情報を含める。リポジトリにコミットする。 |
以下のようにアプリケーションに .flaskenv
を作成し、flask run
を実行すると2つの値が読み込まれます。
flask-app/ ├── .flaskenv └── flaskapp.py
# .flaskenv
FLASK_APP=flaskapp
FLASK_RUN_PORT=3000
自動読み込みを無効化する方法など、より詳細な設定方法が知りたい方は公式ドキュメントを参照ください。
Command Line Interface — Flask 1.0.2 documentation
FLASK_APPが設定されていない場合の挙動
FLASK_APP
の指定なしにflask run
が実行された場合、app.py
もしくは wsgi.py
が自動的に実行されるようになりました。どちらも存在する場合、wsgi.py
が実行されるようです。
わざわざ FLASK_APP
を指定するのも面倒くさいので、app.py
を使っていこうと思います。
Flask.run() のスキップ
flask run
コマンド実行時に、Pythonスクリプト中の Flask.run()
がスキップされるようになりました。スキップされている場合は Silently ignoring app.run() because the application is run from the flask command line executable. といった警告が出力されます。
バージョン0.12までは、flask run
コマンドで実行するとコード内の Flask.run()
まで実行されてしまいます。それに関する混乱を避けるためにこの修正が加えられました。
flask routes コマンドの追加
flask routes
コマンドで、Flaskアプリケーションのルーティング情報を一覧できるようになりました。次の例では、Flaskアプリケーション、blueprintにそれぞれルーティングを登録、表示しています。
from flask import Flask, Blueprint app = Flask(__name__) @app.route('/hello') def hello(): return "get hello" @app.route('/post', methods=['POST']) def post_hello(): return "post hello" bp = Blueprint('bp', __name__) @bp.route("/bp_hello", methods=['GET', 'POST']) def bp_hello(): return "blueprint" app.register_blueprint(bp)
GETやPOSTといったHTTPメソッドの情報も表示されます。blueprintの場合は、blueprintの名前とメソッドが表示されます。
Endpoint Methods Rule ----------- --------- ----------------------- bp.bp_hello GET, POST /bp_hello hello GET /hello post_hello POST /post static GET /static/<path:filename>
HTTPExceptionのエラーハンドリングの変更
errorhandler(HTTPException)
で、HTTPExceptionのサブクラスの例外をキャッチできないバグが修正されました。
from werkzeug.exceptions import HTTPException app = Flask(__name__) app.errorhandler(HTTPException) def http_exception(e): return "occured http exception"
Flaskのerrorhandler
は指定した例外のサブクラスの例外が発生した場合にもキャッチできます。バージョン0.12までは、NotFound
や Forbidden
といったHTTPExceptionのサブクラスの例外を、errorhandler(HTTPException)
でキャッチできませんでした。この現象の詳細は、過去の記事(HTTPExceptionのサブクラスの例外発生時の挙動の項目) に記載しています。
この修正でHTTPExceptionのサブクラスの例外発生時、同一のエラー画面にリダイレクトするのが楽になりました。
Flask.loggerに関する変更
Flask.logger.handlers
にハンドラーが1つだけ追加されるようになりました。最初にloggerにアクセスしたタイミングでloggingの設定がされていなかったら、実行環境に応じてハンドラーが追加されます。
バージョン0.12までは、デフォルトでdevelopment用とproduction用の2つのハンドラーが登録されていました。そして、実行時の環境に応じてハンドラーが選択されていました。必要なハンドラーだけが登録されるようになり、挙動がシンプルになりました。
詳細な設定方法などは公式ドキュメントを参照してください。
Logging — Flask 1.0.2 documentation
ResponseオブジェクトのJSONサポート
Response.get_json()
で、Responseオブジェクトに含まれるJSONデータを辞書型で取得できるようになりました。この変更により、Request と Response の双方のクラスで、get_json()
や is_json()
が使えるようになりました。バージョン0.12までは、flask.json.loads()
が必要でした。
from flask import Flask, jsonify app = Flask(__name__) @app.route('/test', methods=['POST']) def test(): return jsonify(result='test value') with app.test_client() as c: json_data = c.post('/test').get_json() assert json_data['result'] == 'test value
公式ドキュメントのJSON APIをテストする方法のところに具体例が掲載されています。