CREATIVE X 第2弾
CREATIVE X 第2弾
2018.10.05
バックエンドへの道

「Flask」でのエラーハンドリングについて考える

エリカ

こんにちは、ディレクターのエリカです。

今回はpythonのマイクロフレームワーク「Flask」でのエラーハンドリングについて調べてみました。

独自のエラーページを表示する

まずは、独自の404ページを出力してみます。404ページ用のerrorhandler()を準備しましょう。

errorhandler()を利用すると、指定したエラーコードで動作する関数を登録することができます。今回は、その中で独自の404ページを出力するよう設定します。

これにはデコレータを利用する方法登録関数を利用する方法があります。

①デコレータを利用する場合

まずは、デコレータを利用する方法。

@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

②登録関数を利用する場合

こちらが、エラーハンドラーに直接登録する方法です。

def page_not_found(error):
    return render_template('page_not_found.html'), 404

app.register_error_handler(404, page_not_found)

設定したエラーハンドラーを呼び出す

これで、404ページ用のエラーハンドラーを登録できました。次に、このエラーハンドラーをたとえば「指定したデータが見当たらない」などといった任意のタイミングで実行できるようにします。

from flask import abort

@app.route('/foo')
def foo():
    # 表示すべきデータが見つからなかったとして
    abort(404)

上記で処理は完了です。

任意のエラーコードを利用する方法

404ページの出力以外にも、任意の処理を行うことができます。

指定したエラーコードに応じた処理をそれぞれ指定してみましょう。

認証エラーの専用ページを出力する場合

@app.errorhandler(401)
def unauthorized_error(error):
    return render_template('unauthorized_error.html'), 401

もしくは、

app.register_error_handler(401, unauthorized_error)

このエラーハンドラーを呼び出す場合はこちらです。

if 認証失敗:
    abort(401)

内部エラーの専用ページを出力する場合

@app.errorhandler(500)
def internal_server_error.html(error):
    return render_template('internal_server_error.html'), 500

もしくは、

app.register_error_handler(500, internal_server_error.html)

このエラーハンドラーを呼び出す場合。

except 例外:
    abort(500)

RESTfulなAPIでエラーを表現する

さらに、RESTfulなAPIでのエラーレスポンスを出力することもできます。ここでは、専用の例外クラスを利用してみましょう。

下記のような専用の例外クラスを準備します。

from flask import jsonify

class InvalidUsage(Exception):
    status_code = 400

    def __init__(self, message, status_code=None, payload=None):
        Exception.__init__(self)
        self.message = message
        if status_code is not None:
            self.status_code = status_code
        self.payload = payload

    def to_dict(self):
        rv = dict(self.payload or ())
        rv['message'] = self.message
        return rv

この例外クラスを指定してエラーハンドラーに登録します。

@app.errorhandler(InvalidUsage)
def handle_invalid_usage(error):
    response = jsonify(error.to_dict())
    response.status_code = error.status_code
    return response

あとは、任意のタイミングで、作成した例外を投げるだけです。

raise InvalidUsage('This view is gone', status_code=410)

結果、下記のようなエラーが出力されます。

これで、APIのエラーハンドリング時に任意のメッセージを返却できるようになります。

{
  "message": "This view is gone"
}

まとめ

いかがでしたか? エラーハンドリングで処理をまとめることによって、より簡潔に、かつ的確なエラーメッセージを表示することができるようになります。

せっかくのpython、せっかくのマイクロフレームワークなので、積極的に利用していきたいですね。それではまた!

 
「Flask」を扱ったLIGブログ記事▼