リクエストのコンテキスト(The Request Context) The Request Context

request contextは、リクエストの期間中(訳注: リクエストを受信した後、リクエストへの対応処理が終了してリクエストを終了させるまでの間とほぼ同じ)、リクエストのレベルのデータを把握します。リクエストの期間中に実行されるそれぞれの関数でリクエストのオブジェクトを渡して回るよりも、代わりにプロキシのrequestsessionにアクセスします(訳注: 引数で受け取らなくてもリクエストのオブジェクトに関数内からアクセスできるように、flaskパッケージをimport後flask.requestやflask.sessionにアクセスすればそのとき処理中のリクエストやセッションのオブジェクトにアクセスできるようなことを指しています)。 The request context keeps track of the request-level data during a request. Rather than passing the request object to each function that runs during a request, the :data:`request` and :data:`session` proxies are accessed instead.

これは、リクエストには依存しないアプリケーションのレベルのデータを把握するアプリケーションのコンテキスト(The Application Context)と似ています。request contextがpushされたとき、対応するapplication contextもpushされます(訳注:application contextとrequest contextはFlask内でスタックのデータ構造を使って管理されており、一般的にスタックへデータを追加することをpushといいます)。 This is similar to the :doc:`/appcontext`, which keeps track of the application-level data independent of a request. A corresponding application context is pushed when a request context is pushed.

コンテキストの目的(Purpose of the Context) Purpose of the Context

Flaskアプリケーションがリクエストを処理するとき、WSGIサーバから受け取った環境(訳注: WSGIは、WSGIサーバからWSGIアプリケーションに環境情報をdict互換のオブジェクトで渡す仕様になっています)に基づいてRequestオブジェクトを作成します。worker(サーバによって、スレッド、プロセス、またはコルーチンになります)は同時には1つしかリクエストを処理できないため、リクエストのデータはそのリクエストの期間中はworkerにとってグローバルなものと見做すことができます。このことに対してFlaskはcontext localという用語を使用します。 When the :class:`Flask` application handles a request, it creates a :class:`Request` object based on the environment it received from the WSGI server. Because a *worker* (thread, process, or coroutine depending on the server) handles only one request at a time, the request data can be considered global to that worker during that request. Flask uses the term *context local* for this.

リクエストを処理するとき、Flaskは自動的にrequest contextをpushします。リクエストの期間中に実行するview関数、エラー処理、およびその他の関数が、その時点のリクエストに対応するリクエストのオブジェクトへのプロキシになるrequestへアクセスします。 Flask automatically *pushes* a request context when handling a request. View functions, error handlers, and other functions that run during a request will have access to the :data:`request` proxy, which points to the request object for the current request.

コンテキストの生存期間(Lifetime of the Context) Lifetime of the Context

Flaskアプリケーションがリクエストの処理を始めるとき、Flaskアプリケーションはrequest contextとアプリケーションのコンテキスト(The Application Context)をpushします。リクエストが終了するとき、Flaskアプリケーションはrequest contextをpopし(訳注: 一般的にスタックからデータを取り出すことをpopといいます)、それからapplication contextをpopします。 When a Flask application begins handling a request, it pushes a request context, which also pushes an :doc:`/appcontext`. When the request ends it pops the request context then the application context.

contextは各スレッド(または他のworkerタイプ)で固有なものです。requestは、他のスレッドへ渡すことは不可能で、他のスレッドは異なるcontextのスタックを持ち、親スレッドが指しているrequestについて知ることはありません(訳注: 親スレッドのrequestプロキシが指している実際のリクエストは、子スレッドのrequestプロキシが指すものとは異なるというような意味合い)。 The context is unique to each thread (or other worker type). :data:`request` cannot be passed to another thread, the other thread will have a different context stack and will not know about the request the parent thread was pointing to.

context localはWerkzeugの中で実装されています。これが内部的にはどのように働くかについてのさらなる情報はContext Localsを確認してください。 Context locals are implemented in Werkzeug. See :doc:`werkzeug:local` for more information on how this works internally.

手作業でのコンテキストの登録(Manually Push a Context) Manually Push a Context

もしrequestまたはrequestを使うものへのアクセスを試すとき、request contextの外側の場合(request contextがスタックへpushされた状態でない場合)、以下のようなエラーメッセージを得るでしょう: If you try to access :data:`request`, or anything that uses it, outside a request context, you'll get this error message:

RuntimeError: Working outside of request context.

This typically means that you attempted to use functionality that
needed an active HTTP request. Consult the documentation on testing
for information about how to avoid this problem.

これは典型的には、活動中のリクエストを期待しているテスト用コードのときだけ発生するはずです。(解決するための)選択肢のひとつは、リクエスト全体を模擬するためにtest clientを使用することです。または、withブロックの中でFlask.test_request_context()を使用することも可能で、そうすると(以下の例では)ブロックの内側で実行しているものは全て、テストデータが反映されたrequestへアクセスできるようになります。 This should typically only happen when testing code that expects an active request. One option is to use the :meth:`test client <Flask.test_client>` to simulate a full request. Or you can use :meth:`~Flask.test_request_context` in a ``with`` block, and everything that runs in the block will have access to :data:`request`, populated with your test data. ::

def generate_report(year):
    format = request.args.get('format')
    ...

with app.test_request_context(
        '/make_report/2017', data={'format': 'short'}):
    generate_report()

もしテストと関係のない、どこか別の場所のコードでこのエラーを見た場合は、そのコードをview関数の内側へ移動するべきだと示している可能性が最も高いです。 If you see that error somewhere else in your code not related to testing, it most likely indicates that you should move that code into a view function.

インタラクティブなPythonのshellからrequest contextを使うやり方についての情報は、Shellを使った作業を確認してください。 For information on how to use the request context from the interactive Python shell, see :doc:`/shell`.

コンテキストの働きかた(How the Context Works) How the Context Works

Flask.wsgi_app()メソッドは各リクエストを処理するために呼び出されます。それはリクエストの期間中contextを管理します。内部的には、request contextとapplication contextは_request_ctx_stack_app_ctx_stackというスタックとして機能します。contextがスタックにpushされたとき、pushされたものに応じたプロキシ(訳注: flask.requestなどのこと)が利用可能になり、プロキシはスタックの一番上にあるcontextから得られる情報を指すようになります。 The :meth:`Flask.wsgi_app` method is called to handle each request. It manages the contexts during the request. Internally, the request and application contexts work as stacks, :data:`_request_ctx_stack` and :data:`_app_ctx_stack`. When contexts are pushed onto the stack, the proxies that depend on them are available and point at information from the top context on the stack.

リクエストが始まると、RequestContextが作成されpushされ、それは、もしもそのアプリケーションのcontextがまだ(スタックの)一番上のcontextでない場合は、最初にAppContextを作成してpushします。これらのcontextがpushされている間、プロキシであるcurrent_app, g, request, そしてsessionが、そのリクエストを処理しているオリジナルのスレッドから利用できるようになります。 When the request starts, a :class:`~ctx.RequestContext` is created and pushed, which creates and pushes an :class:`~ctx.AppContext` first if a context for that application is not already the top context. While these contexts are pushed, the :data:`current_app`, :data:`g`, :data:`request`, and :data:`session` proxies are available to the original thread handling the request.

contextはスタックなので、他のcontextがリクエストの期間中にプロキシを変更するためにpushされるかもしれません。これはよくあるパターンではないですが、高度なアプリケーションでは、例えば内部的にリダイレクトしたり、違うアプリケーションを一緒に連鎖したりするために、使用可能です。 Because the contexts are stacks, other contexts may be pushed to change the proxies during a request. While this is not a common pattern, it can be used in advanced applications to, for example, do internal redirects or chain different applications together.

リクエストが割り振られ(dispatch)てレスポンスが生成され送信された後、request contextはpopされ、それからapplication contextをpopします。それらがpopされる直前に、teardown_request()teardown_appcontext()関数が実行されます。これらはdispatch中に捕捉されない例外が発生した場合でも実行されます。 After the request is dispatched and a response is generated and sent, the request context is popped, which then pops the application context. Immediately before they are popped, the :meth:`~Flask.teardown_request` and :meth:`~Flask.teardown_appcontext` functions are executed. These execute even if an unhandled exception occurred during dispatch.

コールバックとエラー Callbacks and Errors

Flaskはリクエストを複数の段階に分けながら割り振り(dispatch)、その段階によってリクエスト、レスポンス、そしてエラー処理のされ方は影響を受けることがあります。その全ての段階を通じて、contextは活動中な状態(active)です。 Flask dispatches a request in multiple stages which can affect the request, response, and how errors are handled. The contexts are active during all of these stages.

blueprintはそれらのevent(dispatchするときのstageの変化のような意味合い)に対して、そのblueprint固有のhandlerを追加できます。blueprintのhandlerは、そのblueprintがリクエストに(訳注: 普通はそのURLに)対応する経路(route)を持っていたときに実行します。 A :class:`Blueprint` can add handlers for these events that are specific to the blueprint. The handlers for a blueprint will run if the blueprint owns the route that matches the request.

  1. 各リクエストの前に、before_request()で登録された関数が呼び出されます。もしその関数のうちひとつでも値を返せば、その他の関数はスキップされます。戻り値はレスポンスとして扱われ、view関数は実行されません。 Before each request, :meth:`~Flask.before_request` functions are called. If one of these functions return a value, the other functions are skipped. The return value is treated as the response and the view function is not called.

  2. もしbefore_request()の関数がレスポンスを返さない場合は、経路(route)に対応するview関数が呼び出されてレスポンスを返します。 If the :meth:`~Flask.before_request` functions did not return a response, the view function for the matched route is called and returns a response.

  3. viewの戻り値は実際のレスポンスのオブジェクトへ変換され、after_request()関数へ渡されます。各関数は変更を加えたもしくは新しいレスポンスのオブジェクトを返します。 The return value of the view is converted into an actual response object and passed to the :meth:`~Flask.after_request` functions. Each function returns a modified or new response object.

  4. レスポンスが返された後、contextがpopされ、popされたcontextはteardown_request()teardown_appcontext()関数を呼び出します。これらの関数は、捕捉されない例外が上記のどの点で発生したとしても、呼び出されます。 After the response is returned, the contexts are popped, which calls the :meth:`~Flask.teardown_request` and :meth:`~Flask.teardown_appcontext` functions. These functions are called even if an unhandled exception was raised at any point above.

もし例外がteardown関数の前に発生した場合、Flaskはその例外を処理してレスポンスを返すために、errorhandler()関数に対応付けようと試みます。errorハンドラが見つからない、もしくはハンドラ自身が例外を発生させた場合には、Flaskは汎用的な500 Internal Server Errorレスポンスを返します。その場合でもteardown関数は呼び出され、その例外のオブジェクトが(引数としてteardown関数に)渡されます。 If an exception is raised before the teardown functions, Flask tries to match it with an :meth:`~Flask.errorhandler` function to handle the exception and return a response. If no error handler is found, or the handler itself raises an exception, Flask returns a generic ``500 Internal Server Error`` response. The teardown functions are still called, and are passed the exception object.

もしデバッグモードが有効な場合、捕捉されない例外は500のレスポンスへは変換されず、代わりにWSGIサーバへと伝搬されます。これは、開発用サーバがトレースバック(訳注: 例外に関する情報のひとつ)と一緒にインタラクティブなデバッガを提示できるようにします。 If debug mode is enabled, unhandled exceptions are not converted to a ``500`` response and instead are propagated to the WSGI server. This allows the development server to present the interactive debugger with the traceback.

取り壊しのコールバック(Teardown Callbacks) Teardown Callbacks

teardown callbackはリクエストの割り振りからは独立したもので、代わりにcontextがpopされたときにcontextから呼び出されます。割り振り(dispatch)の間に捕捉されない例外があった場合や、手動でpopされたcontextの場合でも、この関数は呼び出されます。これは、リクエストのdispatchの他の部分(teardown callback以外の部分)はteardown callbackより先に実行している、という保証がどこにもないことを意味します。これらの関数は、他のコールバックに依存せず、他のコールバックへの依存のせいで失敗しないような書き方を、必ずしてください。 The teardown callbacks are independent of the request dispatch, and are instead called by the contexts when they are popped. The functions are called even if there is an unhandled exception during dispatch, and for manually pushed contexts. This means there is no guarantee that any other parts of the request dispatch have run first. Be sure to write these functions in a way that does not depend on other callbacks and will not fail.

テストの間は、テスト用の関数の中でcontextのデータにアクセス可能にするために、リクエストが終わった後でのcontextのpopを遅らせると便利な場合があります。withブロックから抜けるまでの間はcontextを保持するには、test_client()withブロックとして使用してください。 During testing, it can be useful to defer popping the contexts after the request ends, so that their data can be accessed in the test function. Use the :meth:`~Flask.test_client` as a ``with`` block to preserve the contexts until the ``with`` block exits.

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def hello():
    print('during view')
    return 'Hello, World!'

@app.teardown_request
def show_teardown(exception):
    print('after with block')

with app.test_request_context():
    print('during with block')

# teardown functions are called after the context with block exits

with app.test_client() as client:
    client.get('/')
    # the contexts are not popped even though the request ended
    print(request.path)

# the contexts are popped and teardown functions are called after
# the client with block exits

合図(Signals) Signals

もしsignals_availableがtrueの場合、以下のsignalが送られます: If :data:`~signals.signals_available` is true, the following signals are sent:

  1. request_startedbefore_request()関数が呼び出される前に送られます。 :data:`request_started` is sent before the :meth:`~Flask.before_request` functions are called.

  2. request_finishedafter_request()関数が呼び出された後に送られます。 :data:`request_finished` is sent after the :meth:`~Flask.after_request` functions are called.

  3. got_request_exceptionは例外の処理が始まり、まだerrorhandler()が見つかるか呼び出される前に、呼び出されます。 :data:`got_request_exception` is sent when an exception begins to be handled, but before an :meth:`~Flask.errorhandler` is looked up or called.

  4. request_tearing_downteardown_request()関数が呼び出された後で送られます。 :data:`request_tearing_down` is sent after the :meth:`~Flask.teardown_request` functions are called.

エラー時のcontextの保持(Context Preservation on Error) Context Preservation on Error

リクエストの最後に、request contextはpopされ、contextに関連付けられていたデータは全て破壊されます。もし開発中にエラーが発生したとき、デバッグ目的のためにデータの破壊を遅くすると役に立ちます。 At the end of a request, the request context is popped and all data associated with it is destroyed. If an error occurs during development, it is useful to delay destroying the data for debugging purposes.

(Flaskの)開発用サーバが開発モードで走っている(「FLASK_ENV環境変数が'development'に設定されている)とき、エラーとデータは保持されてインタラクティブなデバッガの中で表示されます。 When the development server is running in development mode (the ``FLASK_ENV`` environment variable is set to ``'development'``), the error and data will be preserved and shown in the interactive debugger.

この振る舞いはPRESERVE_CONTEXT_ON_EXCEPTION設定を使って制御可能です。上で説明したように、それは開発環境の標準設定ではTrueです。 This behavior can be controlled with the :data:`PRESERVE_CONTEXT_ON_EXCEPTION` config. As described above, it defaults to ``True`` in the development environment.

例外時にアプリケーションのメモリを漏えい(leak)させる原因になるので、PRESERVE_CONTEXT_ON_EXCEPTIONは本番環境で有効にしないでください。 Do not enable :data:`PRESERVE_CONTEXT_ON_EXCEPTION` in production, as it will cause your application to leak memory on exceptions.

プロキシに関する注意事項(Notes On Proxies) Notes On Proxies

Flaskによって提供されるオブジェクトのいくつかは、他のオブジェクトへのプロキシになります。それらのプロキシは各workerスレッドで同じやり方でアクセスされますが、このページで説明したように目に見えないところで、workerごとに固有のオブジェクトを指します。 Some of the objects provided by Flask are proxies to other objects. The proxies are accessed in the same way for each worker thread, but point to the unique object bound to each worker behind the scenes as described on this page.

殆どの場合、あなたがこのことを気に掛ける必要はありませんが、このオブジェクトが実際にはプロキシであると知っておくとよい、いくつかの例外があります: Most of the time you don't have to care about that, but there are some exceptions where it is good to know that this object is actually a proxy:

  • このプロキシのオブジェクトは、実際のオブジェクトのtypeを偽装することはできません。もしインスタンス(のtype)のチェックをしたいときは、プロキシの背後にある(実際の)オブジェクトに対して行う必要があります。 The proxy objects cannot fake their type as the actual object types. If you want to perform instance checks, you have to do that on the object being proxied.

  • 例えば合図(Signals)を送ったりバックグラウンドのスレッドにデータを渡したりするときなど、ある状況では、proxyされているオブジェクトへの参照(object reference)が必要になります。 The reference to the proxied object is needed in some situations, such as sending :doc:`signals` or passing data to a background thread.

もしプロキシされている土台のオブジェクトへのアクセスが必要な場合は、_get_current_object()メソッドを使用してください: If you need to access the underlying object that is proxied, use the :meth:`~werkzeug.local.LocalProxy._get_current_object` method::

app = current_app._get_current_object()
my_signal.send(app)