(編集 - gevent.monkey.patch_all() - wsgy.py スクリプト ファイルで実行 - 自動的にスレッド ローカルにパッチを適用して greenlet ローカルにするため、Werkzeug を使用するこの代替手段は GEvent (または Gevent ワーカーを使用する GUnicorn) には必要ありません。 、GEventなしでグリーンレットを使用する場合、このソリューションが必要になる場合があります)
Flask Frameworkを思い出すと、答えが見つかりました。
Flask は、「グローバルに」多くのオブジェクトをサポートし、オブジェクトのように「見える」フレームsession
ワークrequest
ですthreading.local
。主な違いは、それらがスレッド ローカルではなくコンテキスト ローカルであることと、コンテキストが現在の実行スタックであることです。
スレッドには独自のコンテキストがあります (したがって、スレッド理論について読むときのコンテキスト スイッチの概念です)。プロセスには、スレッド (およびメイン スレッド) を含むコンテキストがあります。
これまでのところ、私たちが知っている理論では、プロセスにはスレッドが含まれ、スレッドには独自の実行コンテキストが含まれます。スレッドが独自のデータ コンテキストを作成できない限り、データは常に共有されます。ここで、スレッド ローカル (変数/データ)の概念が登場します。
しかし、この同時実行の概念に対処し、C10K の問題を考慮すると、対応するコンテキスト スイッチを使用して複数のブロック スレッドを使用する代わりに、1 つのスレッドでの非同期実行が優先されました (特に、デフォルトの python distr0 に GIL がある python に関して)。Greenlet は同じスレッド スイッチング コンテキストとして作成され、階層が変更されました。
Process 1--* thread 1--* greenlet (and now the requests are here)
そのため、Greenlets の概念は、 Geventのようなサーバーの Python で作成および実装されました。リクエストはスレッドにバインドされなくなったため、スレッド ローカル データを使用できなくなりました (つまり、同じスレッドローカル コンテキストを共有し、データを競合する可能性があります)。
現在、コンテキスト自体が greenlet であり、スレッド ローカルではなくコンテキスト ローカルの概念が必要です。
では、Flask はリクエストごとにデータを分離するコンテキスト ローカルをどのように使用するのでしょうか? (例: セッション、リクエスト)。コンテキストに依存しない分離に対する答えは次のとおりです。
Werkzeug のコンテキスト ローカル
Werkzeug と Flask の作成者は同じです。Werkzeug はフレームワークではなく、任意の WSGI フレームワーク( Djangoなど)で使用できる一連のユーティリティにすぎません。フレームワーク自体は Flask であり、実際には Werkzeug のユーティリティに依存しています。
Werkzeug のコンテキスト ローカルは、greenlet 固有のデータを保存し、スレッドローカル:
#a python module for my django project where I define
#a custom field class which statically needs to know the
#current request.
#I was using, instead, a threadlocal. The usage is THE SAME.
#the main difference is that threads are GCed, while contexts
#not necessarily, so you must ALWAYS release them explicitly
#using release_local, for the current context.
#this code below used to have `threading.local` instances
#instead of `werkzeug.local.Local` instances.
#as I said before, assigning data works like before, but
#the main difference is when releasing the data.
from werkzeug.local import Local, release_local
class AutocompleteField(object):
DATA = Local()
@staticmethod
def set_request(request):
AutocompleteField.DATA.request = request
@staticmethod
def unset_request(request):
release_local(AutocompleteField.DATA)
@staticmethod
def get_request():
try:
return AutocompleteField.DATA.request
except AttributeError as e:
return None