アプリケーションのエラーの処理 Handling Application Errors

アプリケーションには障害が発生し、サーバにも障害が発生します。遅かれ早かれ、本番環境で例外(exception)が見つかるでしょう。もしコードが100%正しいとしても、時には例外が見つかります。なぜでしょうか?コード以外の関連する全てモノに障害が発生するためです。ここでは、完全によくできたコードがサーバのエラーに至る状況をいくつか示します: Applications fail, servers fail. Sooner or later you will see an exception in production. Even if your code is 100% correct, you will still see exceptions from time to time. Why? Because everything else involved will fail. Here are some situations where perfectly fine code can lead to server errors:

  • クライアントがリクエストを早いうちに終了させて、アプリケーションが受信データの読み取り中です the client terminated the request early and the application was still reading from the incoming data

  • データベース・サーバが過負荷であり、問合せ(query)を処理できません the database server was overloaded and could not handle the query

  • ファイルシステムに空きがありません a filesystem is full

  • ハードドライブ(ハードディスク)がクラッシュしました a harddrive crashed

  • 背後(backend)のサーバが過負荷です a backend server overloaded

  • 使用しているライブラリにプログラムのエラーがあります a programming error in a library you are using

  • サーバから他のシステムへのネットワーク接続に障害が発生しました network connection of the server to another system failed

そして、これは直面するであろう問題の小さなサンプルでしかありません。ではこのような問題にどう対処するのでしょうか?標準設定では、もしアプリケーションが本番環境(production)モードで走っていて、例外が生じた場合、Flaskはとてもシンプルなページを表示し、loggerへ例外をログします。 And that's just a small sample of issues you could be facing. So how do we deal with that sort of problem? By default if your application runs in production mode, and an exception is raised Flask will display a very simple page for you and log the exception to the :attr:`~flask.Flask.logger`.

しかし、もっとできることがあり、独自の例外と3rd partyツールを含む、エラーを処理するためのより良いいくつかの準備(setup)についてこの文書で扱います。 But there is more you can do, and we will cover some better setups to deal with errors including custom exceptions and 3rd party tools.

エラーログ処理ツール Error Logging Tools

エラーメールを送信していると、たとえ非常に重大なものだけにした場合でも、多くのユーザがエラーに当たると圧倒されるものになり、典型的にはログファイルは見られなくなります。これが、アプリケーションのエラー処理のためにSentryを勧める理由です。それはGitHub上でソース入手可能なプロジェクトとして利用可能であり、無料で試すことのできるホストされたバージョンとしても利用可能です。Sentryは重複するエラーを収集し、デバッグのためにスタックトレース全体とローカル変数を捕捉し、そして新しいエラーであるか、もしくは閾値を超える頻度であることに基づいてメール送信します。 Sending error mails, even if just for critical ones, can become overwhelming if enough users are hitting the error and log files are typically never looked at. This is why we recommend using `Sentry <https://sentry.io/>`_ for dealing with application errors. It's available as a source-available project `on GitHub <https://github.com/getsentry/sentry>`_ and is also available as a `hosted version <https://sentry.io/signup/>`_ which you can try for free. Sentry aggregates duplicate errors, captures the full stack trace and local variables for debugging, and sends you mails based on new errors or frequency thresholds.

Sentryを使うには、sentry-sdkクライアントを、追加分のflask依存対象と一緒にインストールする必要があります。 To use Sentry you need to install the ``sentry-sdk`` client with extra ``flask`` dependencies.

$ pip install sentry-sdk[flask]

そしてそれから、以下をFlaskのappに追加します: And then add this to your Flask app:

import sentry_sdk
from sentry_sdk.integrations.flask import FlaskIntegration

sentry_sdk.init('YOUR_DSN_HERE', integrations=[FlaskIntegration()])

YOUR_DSN_HEREの値は、インストールしたSentryから得たDSNの値に置き換える必要があります。 The ``YOUR_DSN_HERE`` value needs to be replaced with the DSN value you get from your Sentry installation.

インストールの後、Internal Server Errorに至る障害は自動的にSentryへ報告され、そこからエラー通知を受け取ることができます。 After installation, failures leading to an Internal Server Error are automatically reported to Sentry and from there you can receive error notifications.

以下も見てください: See also:

  • Sentryは(RQ, Celery(訳注: RQ・Celeryともに、ジョブをキューに投入し、ワーカーでキューからジョブを取り出して実行させる、ジョブキューのPythonのライブラリ)のような)ワーカーのキューでのエラーを同じように捕捉することもサポートしています。さらなる情報はPython SDKドキュメントを見てください。 Sentry also supports catching errors from a worker queue (RQ, Celery, etc.) in a similar fashion. See the `Python SDK docs <https://docs.sentry.io/platforms/python/>`__ for more information.

  • Sentry入門 `Getting started with Sentry <https://docs.sentry.io/quickstart/?platform=python>`__

  • Flask固有のドキュメント `Flask-specific documentation <https://docs.sentry.io/platforms/python/guides/flask/>`__

エラー処理器(Error Handlers) Error Handlers

Flaskの中でエラーが起きたとき、適切なHTTPステータスコードが返されます。400-499はクライアントのリクエストのデータに、もしくは要求されたデータに関してエラーがあることを示します。500-599はサーバもしくはアプリケーション自身にエラーがあることを示します。 When an error occurs in Flask, an appropriate `HTTP status code <https://developer.mozilla.org/en-US/docs/Web/HTTP/Status>`__ will be returned. 400-499 indicate errors with the client's request data, or about the data requested. 500-599 indicate errors with the server or application itself.

エラーが起きたとき、独自のエラーページを見せたいかもしれません。これは、error handlerを登録することで可能です。 You might want to show custom error pages to the user when an error occurs. This can be done by registering error handlers.

error handlerは、viewがリクエストのURLに合致したときレスポンスを返す関数であることに似たように、ある種類のエラーが起きたときにレスポンスを返す関数です。error handlerには、HTTPExceptionである可能性が最も高い、処理中のエラーのインスタンスが渡されます。 An error handler is a function that returns a response when a type of error is raised, similar to how a view is a function that returns a response when a request URL is matched. It is passed the instance of the error being handled, which is most likely a :exc:`~werkzeug.exceptions.HTTPException`.

レスポンスのステータスコードはerror handlerのコードには設定されません。error handlerからレスポンスを返すときは、適切なHTTPステータスコードを確実に提供するようにしてください。 The status code of the response will not be set to the handler's code. Make sure to provide the appropriate HTTP status code when returning a response from a handler.

登録 Registering

errorhandler()を使って関数を修飾(decorating)してhandlerを登録します(訳注: Pythonのdecorator機能を使って登録します)。または、register_error_handler()を使って、後から関数を登録します。レスポンスを返すときにはエラーコードを設定することを覚えておいてください。 Register handlers by decorating a function with :meth:`~flask.Flask.errorhandler`. Or use :meth:`~flask.Flask.register_error_handler` to register the function later. Remember to set the error code when returning the response.

@app.errorhandler(werkzeug.exceptions.BadRequest)
def handle_bad_request(e):
    return 'bad request!', 400

# or, without the decorator
app.register_error_handler(400, handle_bad_request)

BadRequestのようなwerkzeug.exceptions.HTTPExceptionのサブクラスとそれらのHTTPコードは、handlerを登録するとき相互に交換可能です。(BadRequest.code == 400 :exc:`werkzeug.exceptions.HTTPException` subclasses like :exc:`~werkzeug.exceptions.BadRequest` and their HTTP codes are interchangeable when registering handlers. (``BadRequest.code == 400``)

非標準のHTTPコード(訳注: HTTPプロトコルの仕様に定義されていないHTTPレスポンスコード)はWerkzeugで分からないため、コードによる登録ができません。代わりに、適切なコードを使ってHTTPExceptionのサブクラスを定義し、そのクラス(とhandler)を登録し、その例外クラス(の例外)を発生させます。 Non-standard HTTP codes cannot be registered by code because they are not known by Werkzeug. Instead, define a subclass of :class:`~werkzeug.exceptions.HTTPException` with the appropriate code and register and raise that exception class.

class InsufficientStorage(werkzeug.exceptions.HTTPException):
    code = 507
    description = 'Not enough storage space.'

app.register_error_handler(InsufficientStorage, handle_507)

raise InsufficientStorage()

handlerは、HTTPExceptionサブクラスまたはHTTPステータスコードに対してだけでなく、どのような例外クラスに対しても登録可能です。handlerは特定のクラスに対しても、ある親クラスの全てのサブクラスに対しても、登録可能です。 Handlers can be registered for any exception class, not just :exc:`~werkzeug.exceptions.HTTPException` subclasses or HTTP status codes. Handlers can be registered for a specific class, or for all subclasses of a parent class.

処理(Handling) Handling

アプリケーションを構築していると、例外に出くわすでしょう。もしもリクエストの処理中に自分のコードの一部が壊れた(そしてerror handlerが登録されていなかった)場合、「500 Internal Server Error」(InternalServerError)が標準では返されます。同様に、登録されていない経路(route)にリクエストが送られた場合は「404 Not Found」(NotFound)エラーが起きます。もしもある経路(route)で許可されていないリクエストのメソッド(訳注: HTTPメソッドのこと)を受け取ったときは、「405 Method Not Allowed」(MethodNotAllowed)が起きます。これらは全てHTTPExceptionのサブクラスであり、Flaskでは標準で提供されます。 When building a Flask application you *will* run into exceptions. If some part of your code breaks while handling a request (and you have no error handlers registered), a "500 Internal Server Error" (:exc:`~werkzeug.exceptions.InternalServerError`) will be returned by default. Similarly, "404 Not Found" (:exc:`~werkzeug.exceptions.NotFound`) error will occur if a request is sent to an unregistered route. If a route receives an unallowed request method, a "405 Method Not Allowed" (:exc:`~werkzeug.exceptions.MethodNotAllowed`) will be raised. These are all subclasses of :class:`~werkzeug.exceptions.HTTPException` and are provided by default in Flask.

FlaskはWerkzeugによって登録されているあらゆるHTTP例外を発生させる能力を提供します。しかしながら、標準のHTTP例外はシンプルな例外ページを返します。エラーが起きたとき、独自のエラーページを見せたいかもしれません。これは、error handlerを登録することで可能です。 Flask gives you the ability to raise any HTTP exception registered by Werkzeug. However, the default HTTP exceptions return simple exception pages. You might want to show custom error pages to the user when an error occurs. This can be done by registering error handlers.

リクエストを処理しているときに例外がFlaskによって捕捉されたとき、handlerは最初にコード(訳注: HTTPコードのことだと思います)によって検索されます。もしコードに対するhandlerが登録されてない場合、Flaskはクラス階層によってエラーを検索します; 最も具体的な(訳注: クラス階層上で最もサブクラス化された)handlerが選ばれます。もしhandlerが登録されていない場合、HTTPExceptionのサブクラスはそのコードに関する汎用的なメッセージを表示し、その他の例外は汎用的な「500 Internal Server Error」へ変換されます。 When Flask catches an exception while handling a request, it is first looked up by code. If no handler is registered for the code, Flask looks up the error by its class hierarchy; the most specific handler is chosen. If no handler is registered, :class:`~werkzeug.exceptions.HTTPException` subclasses show a generic message about their code, while other exceptions are converted to a generic "500 Internal Server Error".

例えば、もしConnectionRefusedErrorのインスタンスが発生し、そしてConnectionErrorConnectionRefusedErrorに対するhandlerが登録されていた場合、レスポンスを生成するために、最も具体的なConnectionRefusedErrorのhandlerが例外のインスタンスを使って呼び出されます。 For example, if an instance of :exc:`ConnectionRefusedError` is raised, and a handler is registered for :exc:`ConnectionError` and :exc:`ConnectionRefusedError`, the more specific :exc:`ConnectionRefusedError` handler is called with the exception instance to generate the response.

blueprintに登録されたhandlerは、blueprintが例外を発生させたリクエストを処理することを仮定して、アプリケーションでグローバルに登録されたものよりも優先されます。しかしながら、404エラーはblueprintが決定される前の経路決定(routing)のレベルで起こるため、blueprintでは404 routing errorは処理できません。 Handlers registered on the blueprint take precedence over those registered globally on the application, assuming a blueprint is handling the request that raises the exception. However, the blueprint cannot handle 404 routing errors because the 404 occurs at the routing level before the blueprint can be determined.

汎用の例外の処理器(Generic Exception Handlers) Generic Exception Handlers

非常に汎用的な基底クラスへ対して、例えばHTTPExceptionまたはExceptionにさえ、error handlerを登録することができます。しかしながら、これらはおそらくあなたが予想するよりも多くのものを捕捉するであろうことに注意してください。 It is possible to register error handlers for very generic base classes such as ``HTTPException`` or even ``Exception``. However, be aware that these will catch more than you might expect.

例えば、HTTPExceptionに対するerror handlerは、標準のHTMLエラーページをJSONへ変換するには便利かもしれません。しかしながら、このhandlerは、例えば経路決定(routing)のときの404と405エラーのように、あなたが直接引き起こさないものに対しても発動するでしょう。HTTPエラーに関する情報を失わないように、自分のhandlerは必ず注意して作り上げるようにしてください。 For example, an error handler for ``HTTPException`` might be useful for turning the default HTML errors pages into JSON. However, this handler will trigger for things you don't cause directly, such as 404 and 405 errors during routing. Be sure to craft your handler carefully so you don't lose information about the HTTP error.

from flask import json
from werkzeug.exceptions import HTTPException

@app.errorhandler(HTTPException)
def handle_exception(e):
    """Return JSON instead of HTML for HTTP errors."""
    # start with the correct headers and status code from the error
    response = e.get_response()
    # replace the body with JSON
    response.data = json.dumps({
        "code": e.code,
        "name": e.name,
        "description": e.description,
    })
    response.content_type = "application/json"
    return response

Exceptionに対するerror handlerは、全てのエラー、処理されてないものさえも、ユーザへどのように表示するかを変更するには便利にみえるかもしれません。しかしながら、これはPythonでexcept Exception:を行うことと似たものであり、それは、さもなければ処理されないエラーを全て、HTTPステータスコードを含めて、捕捉するでしょう。 An error handler for ``Exception`` might seem useful for changing how all errors, even unhandled ones, are presented to the user. However, this is similar to doing ``except Exception:`` in Python, it will capture *all* otherwise unhandled errors, including all HTTP status codes.

殆どの場合、より具体的な例外に対するhandlerを登録する方がより安全です。HTTPExceptionのインスタンスは正当なWSGIレスポンスなので、それらを直接そのまま渡すことも可能です。 In most cases it will be safer to register handlers for more specific exceptions. Since ``HTTPException`` instances are valid WSGI responses, you could also pass them through directly.

from werkzeug.exceptions import HTTPException

@app.errorhandler(Exception)
def handle_exception(e):
    # pass through HTTP errors
    if isinstance(e, HTTPException):
        return e

    # now you're handling non-HTTP exceptions only
    return render_template("500_generic.html", e=e), 500

error handlerでも例外のクラス階層を尊重します。もしHTTPExceptionExceptionの両方に対してhandlerを登録した場合、HTTPExceptionのhandlerの方がより具体的であるため、ExceptionのhandlerはHTTPExceptionサブクラスを処理しません。 Error handlers still respect the exception class hierarchy. If you register handlers for both ``HTTPException`` and ``Exception``, the ``Exception`` handler will not handle ``HTTPException`` subclasses because it the ``HTTPException`` handler is more specific.

処理されなかった例外(Unhandled Exceptions) Unhandled Exceptions

例外に対してerror handlerが登録されていないとき、500 Internal Server Errorが代わりに返されます。この振る舞いに関する情報についてはflask.Flask.handle_exception()を見てください。 When there is no error handler registered for an exception, a 500 Internal Server Error will be returned instead. See :meth:`flask.Flask.handle_exception` for information about this behavior.

InternalServerErrorに対してerror handlerが登録されていた場合、これが呼び起されます。Flask 1.1.0以降、このerror handlerにはオリジナルの処理されなかったエラーではなく、常にInternalServerErrorのインスタンスが渡されます。 If there is an error handler registered for ``InternalServerError``, this will be invoked. As of Flask 1.1.0, this error handler will always be passed an instance of ``InternalServerError``, not the original unhandled error.

オリジナルのエラーはe.original_exceptionとして利用可能です。 The original error is available as ``e.original_exception``.

「500 Internal Server Error」用のerror handlerには明示的な500エラーに加えて、捕捉されていない例外も渡されます。デバッグモードの中では、「500 Internal Server Error」用のerror handlerは使われません。代わりに、インタラクティブなデバッガが表示されます。 An error handler for "500 Internal Server Error" will be passed uncaught exceptions in addition to explicit 500 errors. In debug mode, a handler for "500 Internal Server Error" will not be used. Instead, the interactive debugger will be shown.

カスタマイズしたエラーページ Custom Error Pages

Flaskアプリケーションを構築しているときに時々、リクエストが何かしらおかしいことをユーザへ伝える信号を送るためにHTTPExceptionを起こしたくなるかもしれません。幸いにも、werkzeugからHTTPエラーを使って望むままにリクエストを中止させる、便利なabort()関数がFlaskにはついて来ています。それは基本的な説明を伴った素っ気ない白黒のエラーページを提供しますが、意匠をこらしたものではありません。 Sometimes when building a Flask application, you might want to raise a :exc:`~werkzeug.exceptions.HTTPException` to signal to the user that something is wrong with the request. Fortunately, Flask comes with a handy :func:`~flask.abort` function that aborts a request with a HTTP error from werkzeug as desired. It will also provide a plain black and white error page for you with a basic description, but nothing fancy.

エラーコードに応じてそのようなエラーをユーザが実際に見ることは多少なりともありそうなことです。 Depending on the error code it is less or more likely for the user to actually see such an error.

以下のコードを考えたとき、おそらくシステムはユーザのプロフィール用の経路(route)を持ち、もしもユーザがusernameを渡せなかった場合は「400 Bad Request」を起こすことができます。もしもユーザがusernameを渡してシステムがそのユーザを見つけられない場合、「404 Not Found」を起こすことができます。 Consider the code below, we might have a user profile route, and if the user fails to pass a username we can raise a "400 Bad Request". If the user passes a username and we can't find it, we raise a "404 Not Found".

from flask import abort, render_template, request

# a username needs to be supplied in the query args
# a successful request would be like /profile?username=jack
@app.route("/profile")
def user_profile():
    username = request.arg.get("username")
    # if a username isn't supplied in the request, return a 400 bad request
    if username is None:
        abort(400)

    user = get_user(username=username)
    # if a user can't be found by their username, return 404 not found
    if user is None:
        abort(404)

    return render_template("profile.html", user=user)

以下は「404 Page Not Found」用の別の実装例です: Here is another example implementation for a "404 Page Not Found" exception:

from flask import render_template

@app.errorhandler(404)
def page_not_found(e):
    # note that we set the 404 status explicitly
    return render_template('404.html'), 404

以下はアプリケーション製造工場(Application Factories)使用時の例です: When using :doc:`/patterns/appfactories`:

from flask import Flask, render_template

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

def create_app(config_filename):
    app = Flask(__name__)
    app.register_error_handler(404, page_not_found)
    return app

テンプレート例は以下のようになるでしょう: An example template might be this:

{% extends "layout.html" %}
{% block title %}Page Not Found{% endblock %}
{% block body %}
  <h1>Page Not Found</h1>
  <p>What you were looking for is just not there.
  <p><a href="{{ url_for('index') }}">go somewhere nice</a>
{% endblock %}

さらなる例(Further Examples) Further Examples

上記の例は標準の例外ページに対する改善に実際にはなっていないでしょう。以下のようにカスタマイズした500.htmlテンプレートを作ることができます: The above examples wouldn't actually be an improvement on the default exception pages. We can create a custom 500.html template like this:

{% extends "layout.html" %}
{% block title %}Internal Server Error{% endblock %}
{% block body %}
  <h1>Internal Server Error</h1>
  <p>Oops... we seem to have made a mistake, sorry!</p>
  <p><a href="{{ url_for('index') }}">Go somewhere nice instead</a>
{% endblock %}

これは「500 Internal Server Error」のテンプレートを変換表示することで実装出来ます: It can be implemented by rendering the template on "500 Internal Server Error":

from flask import render_template

@app.errorhandler(500)
def internal_server_error(e):
    # note that we set the 500 status explicitly
    return render_template('500.html'), 500

以下はアプリケーション製造工場(Application Factories)使用時の例です: When using :doc:`/patterns/appfactories`:

from flask import Flask, render_template

def internal_server_error(e):
  return render_template('500.html'), 500

def create_app():
    app = Flask(__name__)
    app.register_error_handler(500, internal_server_error)
    return app

以下はBlueprintを使ったアプリケーションのモジュール化使用時の例です: When using :doc:`/blueprints`:

from flask import Blueprint

blog = Blueprint('blog', __name__)

# as a decorator
@blog.errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'), 500

# or with register_error_handler
blog.register_error_handler(500, internal_server_error)

ブループリントのエラー処理器(Blueprint Error Handlers) Blueprint Error Handlers

Blueprintを使ったアプリケーションのモジュール化の中で、殆どのerrorhandlerは、予想したとおりに動きます; しかし、404と405のerror handlerに関して注意点があります(訳注: HTTPレスポンスのステータスコードを指していて、404は「Not Found」、405は「Method Not Allowed」になります)。これらのerror handlerが起動されるのは、適切なraise文またはblueprint内の他のview関数の中でabortを呼んだときだけです; それらは、例えば不正なURLへのアクセスからは起動されません。 In :doc:`/blueprints`, most error handlers will work as expected. However, there is a caveat concerning handlers for 404 and 405 exceptions. These error handlers are only invoked from an appropriate ``raise`` statement or a call to ``abort`` in another of the blueprint's view functions; they are not invoked by, e.g., an invalid URL access.

これは、blueprintはあるURL空間を「所有」しておらず、従ってアプリケーションのインスタンスは不正なURLを渡されたとしても、どのblueprintのerror handlerを実行すればよいかを知るすべがないためです。もしURLプレフィックスに基づいて、これらのエラーに対して異なる処理戦略を実行したいときは、それらはアプリケーションのレベルでrequestの代理(proxy)のオブジェクト(訳注: 実際にリクエストを扱うwerkzeugのリクエスト用オブジェクトの、実際のインスタンスへグローバルなスコープでアクセスするためのproxyになっているオブジェクトで、普通はflask.requestオブジェクトのことだと思います)で定義させることができます。 This is because the blueprint does not "own" a certain URL space, so the application instance has no way of knowing which blueprint error handler it should run if given an invalid URL. If you would like to execute different handling strategies for these errors based on URL prefixes, they may be defined at the application level using the ``request`` proxy object.

from flask import jsonify, render_template

# at the application level
# not the blueprint level
@app.errorhandler(404)
def page_not_found(e):
    # if a request is in our blog URL space
    if request.path.startswith('/blog/'):
        # we return a custom blog 404 page
        return render_template("blog/404.html"), 404
    else:
        # otherwise we return our generic site-wide 404 page
        return render_template("404.html"), 404

@app.errorhandler(405)
def method_not_allowed(e):
    # if a request has the wrong method to our API
    if request.path.startswith('/api/'):
        # we return a json saying so
        return jsonify(message="Method Not Allowed"), 405
    else:
        # otherwise we return a generic site-wide 405 page
        return render_template("405.html"), 405

JSONでのAPIエラーの応答(Returning API Errors as JSON) Returning API Errors as JSON

FlaskでAPIを構築するとき、開発者の中には、組み込みの例外ではAPIにとって十分に表現しきれず、組み込みの例外が発行するtext/htmlコンテント・タイプではAPI使用者にとってあまり便利ではないことを実感するでしょう。 When building APIs in Flask, some developers realise that the built-in exceptions are not expressive enough for APIs and that the content type of :mimetype:`text/html` they are emitting is not very useful for API consumers.

上記と同じ技法とjsonify()を使い、APIのエラーに対してJSONを返すことができます。abort()descriptionパラメータと一緒に呼び出されます。error handlerがそれをJSONのエラーメッセージとして使用し、ステータスコードを404に設定します。 Using the same techniques as above and :func:`~flask.json.jsonify` we can return JSON responses to API errors. :func:`~flask.abort` is called with a ``description`` parameter. The error handler will use that as the JSON error message, and set the status code to 404.

from flask import abort, jsonify

@app.errorhandler(404)
def resource_not_found(e):
    return jsonify(error=str(e)), 404

@app.route("/cheese")
def get_one_cheese():
    resource = get_resource()

    if resource is None:
        abort(404, description="Resource not found")

    return jsonify(resource)

カスタマイズした例外クラスを作成することもできます。例えば、人が読める適当なメッセージ、エラー用のステータスコード、そして必要に応じてエラーのより多くの状況を与えるペイロードを持つカスタマイズした新しい例外をAPI用に導入できます。 We can also create custom exception classes. For instance, we can introduce a new custom exception for an API that can take a proper human readable message, a status code for the error and some optional payload to give more context for the error.

以下はシンプルな例です: This is a simple example:

from flask import jsonify, request

class InvalidAPIUsage(Exception):
    status_code = 400

    def __init__(self, message, status_code=None, payload=None):
        super().__init__()
        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(InvalidAPIUsage)
def invalid_api_usage(e):
    return jsonify(e.to_dict()), e.status_code

# an API app route for getting user information
# a correct request might be /api/user?user_id=420
@app.route("/api/user")
def user_api(user_id):
    user_id = request.arg.get("user_id")
    if not user_id:
        raise InvalidAPIUsage("No user id provided!")

    user = get_user(user_id=user_id)
    if not user:
        raise InvalidAPIUsage("No such user!", status_code=404)

    return jsonify(user.to_dict())

こうすると、viewはエラーメッセージと一緒にその例外を起こすことができます。さらに、いくらかの追加のペイロードはpayloadパラメータを通してdictionaryとして提供できるようになります。 A view can now raise that exception with an error message. Additionally some extra payload can be provided as a dictionary through the `payload` parameter.

ログ処理(Logging) Logging

どのように例外をログするか、例えば管理者へメールするなど、についての情報はログ処理(Logging)を見てください。 See :doc:`/logging` for information about how to log exceptions, such as by emailing them to admins.

デバッグ処理(Debugging) Debugging

開発中および本番環境中でどのようにエラーをデバッグするかに関する情報についてはアプリケーション・エラーのデバッグを確認してください。 See :doc:`/debugging` for information about how to debug errors in development and production.