(機械翻訳) スレッドローカル

A:term: `thread local`変数は、それを使用するアプリケーションにとっては「グローバル変数」であるように見える変数です。ただし、真のグローバル変数とは異なり、アプリケーションに対応するスレッドまたはプロセスは、その変数が「スレッドローカル」である場合、別のスレッドまたはプロセスとは異なる値を受け取ることがあります。

リクエストが処理されるとき、:app: Pyramid`は、アプリケーションに利用可能な2つのterm: thread local`変数を作成します:"レジストリ"と"要求"。

理由と方法:app: `Pyramid`はスレッドローカル変数を使用します

スレッド地方はどのように有益でしょう:app: Pyramid`とアプリケーション開発者:app: Pyramid`?まあ、通常、彼らは明らかに**ではありません**。どのアプリケーションでもグローバルまたはスレッドのローカル変数を使用すると、通常、カジュアルな読者にとっては理解するのがずっと難しくなります。スレッドのローカルまたはグローバルの使用は、通常、コード間の可読性が重要な問題とみなされる場合には、通常は非常に悪い考えである関数間で値を渡すことを避けるための方法です。

しかし歴史的な理由から、スレッドローカル変数は、実際には:app: Pyramid API関数によって参照されます。例えば:func: 〜pyramid.security.authenticated_userid`(1.5で廃止予定)という名前の:mod: pyramid.security`関数の実装は、スレッドlocal:term: `アプリケーションレジストリ`をもちろん取得します:term: `認証ポリシー`を見つける。これは、:func: `pyramid.threadlocal.get_current_registry`関数を使ってアプリケーションのレジストリを取得し、そこから認証ポリシーを検索します。認証ポリシーを使用して、認証されたユーザーIDを取得します。 app: `Pyramid`は、任意の認証ポリシーを"プラグイン"にすることができます。

彼らがそうする必要があるとき、:app: Pyramid`内部は:term: request`と:term: application registry::func:〜pyramid.threadlocal.get_current_request`と:func : `〜pyramid.threadlocal.get_current_registry。前者は"現在の"要求を返します。後者は"現在の"レジストリを返します。両方の `` get_current_ * ``関数は、スレッドローカルデータ構造からオブジェクトを取得します。これらのAPI関数は:ref: `threadlocal_module`に記述されています。

これらの値は真のグローバルではなくスレッドローカルです。一つのPythonプロセスが複数の同時リクエスト、あるいは複数の:app: Pyramid`アプリケーションを扱うかもしれないからです。それらが真のグローバルであれば、:app: `Pyramid`は複数の同時リクエストを処理できないか、複数の:app: Pyramid`アプリケーションインスタンスを単一のPythonプロセスに存在させることができませんでした。

one:app: Pyramid`アプリケーションは、それ自身の:term: view`コードから別の*:app: Pyramid`アプリケーションを呼び出すことができます(おそらく、:term: WSGI` app: : `pyramid.wsgi.wsgiapp2`デコレータ)、これらの変数は通常のシステム操作中に* stack *で管理されます。スタックインスタンス自体は:class: `threading.local`です。

通常の操作の間、スレッドローカルスタックは:term: `Router`オブジェクトによって管理されます。要求の開始時に、ルータはアプリケーションのレジストリと要求をスタックにプッシュします。リクエストの最後に、スタックがポップされます。スタックの一番上の要求とレジストリは"現在の"とみなされます。したがって、システムが正常に動作しているとき、"現在の"の定義はピラミッド:用語:ルータの動作によって完全に定義されます。

しかし、ユニットテスト中には、ルータコードは一切呼び出されず、"current "の定義は:meth: pyramid.config.Configurator.begin`と:meth:`ピラミッドの呼び出しの境界によって定義されます。 config.Configurator.end`メソッド(または:func: `pyramid.testing.setUp`関数と:func: pyramid.testing.tearDown`関数の呼び出しの間)を呼び出します。これらの関数は、システムがテスト中のときにスレッドローカルスタックをプッシュしてポップします。これらの関数の定義については:ref: `test_setup_and_teardown`を参照してください。

app: Pyramid`機構を使用するスクリプトでは、実際にWSGIサーバを起動したり、HTTP経由でリクエストを受け取ることはありません。例えば、:mod: pyramid.scripting` APIを使用するスクリプトは、決してルータコードを実行させません。しかし、:mod: pyramid.scripting APIはもちろん、スレッドローカルスタックにいくつかの値をプッシュします。このようなスクリプトは:func: 〜pyramid.threadlocal.get_current_request`関数が常に None``を返すよう期待し、:func:〜pyramid.threadlocal.get_current_registry`関数がまったく同じ:term:リクエストごとに「アプリケーションレジストリ」を作成します。

なぜあなたはスレッドローカルを乱用してはならないのですか?

おそらくテストではなく、:func: 〜pyramid.threadlocal.get_current_request`や:func:〜pyramid.threadlocal.get_current_registry`関数を使うことはほとんどありません。特に、アプリケーションコードで `` get_current_request``や `` get_current_registry``を使うのはほとんどの場合間違いです。なぜなら、その使い方で簡単にテストもスクリプト化もできないコードを書くことができるからです。不適切な使い方は次のように定義されています:

  • `` get_current_request``は、:term: view callable`の本体の中で、あるいはview callableによって呼び出されるコードの中で決して呼び出されるべきではありません。ビュー呼び出し可能な呼び出しはすでにリクエストにアクセスしています( ` request``として渡されます)。
  • `` get_current_request``はterm: `resource`のコードで決して呼び出されるべきではありません。リソースがリクエストにアクセスする必要がある場合は、:term: `view callable`によってリクエストを渡す必要があります。
  • `` get_current_request``関数は、APIデザインを作成する際に一連の関数呼び出しでリクエストを渡すよりも、呼び出しを考える方が"簡単"または"よりエレガントな"という理由で呼び出されるべきではありません。実際にはビジネスを知らない場所でリクエストを取得するためにこの関数を呼び出すことに頼るのではなく、リクエストから導出されたデータを渡すことはほとんど確実です。パラメータは、関数の引数として渡すためのものです。これが存在する理由です。リクエストが必要な場所でこの関数を使用することで、「入力を保存する」または「より良いAPI」を作成しないでください。これは後で悲しみにつながるだけです。
  • 第三者のライブラリコードのアプリケーション固有のフォーク内で、 `` get_current_request``と `` get_current_registry``のどちらも呼び出されるべきではありません。あなたが作ったライブラリは、app: Pyramid`とは関係がありません:app: Pyramid`に依存するようにしてください(あなたの:app: `pyramid`アプリケーションがそれに依存するのではなく)間違った方向への依存関係を形成する。

非常に限られた状況では、アプリケーションコード*内での:func: 〜pyramid.threadlocal.get_current_request`関数の使用はまだ有効です。経験則として、 ` get_current_request``の使用法は、コード内で有用です**は最終的に削除されることを意図しています**。たとえば、リクエストオブジェクトを渡すことを想定しているAPIを非難したいと思うかもしれません。しかし、古いAPIを廃止している間は、古いAPIの実装を一定期間維持する必要があります。したがって、古いAPIを実装するコードを呼び出す新しいAPIの"ファサード"実装を記述します。新しいAPIは要求を必要としないため、ファサード実装は古いAPI実装に渡す必要があるときにリクエストへのローカルアクセスを持ちません。しばらくすると、古い実装コードが使われなくなり、 `` get_current_request``を使ったハックが取り除かれます。これは `` get_current_request``を使うのに適した場所です。

:func: 〜pyramid.threadlocal.get_current_registry`関数の使用は、テストシナリオに限定する必要があります。レジストリは、テスト中に:meth: `pyramid.config.Configurator.begin`メソッドを使用して現在(または:func: pyramid.testing.setUp`経由で)、あなたが渡していないときに、このAPI