[解決済み] Pythonのスレッドローカルストレージ
質問
Pythonでスレッドローカルストレージを使うにはどうしたらいいですか?
関連
- Pythonの "スレッドローカルストレージ "とは何ですか、そしてなぜそれが必要なのですか? - このスレッドは、変数が共有される場合により焦点を当てているように見えます。
- Python で特定の関数がスタック上にあるかどうかを判断するための効率的な方法 - Alex Martelli が素晴らしい解決策を提供しています。
どのように解決するのですか?
スレッドローカルストレージは、例えば、スレッドワーカープールがあり、各スレッドがネットワークやデータベース接続のような独自のリソースにアクセスする必要がある場合に便利です。なお
threading
モジュールは通常のスレッドの概念 (これはプロセスのグローバルデータにアクセスできます) を使いますが、グローバルインタプリタロックがあるため、あまり有用ではありません。異なる
multiprocessing
モジュールはそれぞれ新しいサブプロセスを作成するので、どんなグローバルもスレッドローカルになります。
スレッドモジュール
以下は簡単な例です。
import threading
from threading import current_thread
threadLocal = threading.local()
def hi():
initialized = getattr(threadLocal, 'initialized', None)
if initialized is None:
print("Nice to meet you", current_thread().name)
threadLocal.initialized = True
else:
print("Welcome back", current_thread().name)
hi(); hi()
これで印刷されます。
Nice to meet you MainThread
Welcome back MainThread
見落としがちな重要なこととして
threading.local()
オブジェクトは一度だけ作成されればよく、スレッドごとや関数呼び出しごとに作成される必要はありません。 つまり
global
または
class
レベルは理想的な場所です。
以下はその理由です。
threading.local()
は呼び出されるたびに新しいインスタンスを生成します (ファクトリーやクラスの呼び出しと同じです)。
threading.local()
を何度も呼び出すと、常に元のオブジェクトを上書きすることになります。 どのスレッドも既存の
threadLocal
変数(またはそれが何と呼ばれるものであれ)にアクセスすると、その変数の独自のプライベートビューを取得します。
これは意図した通りには動作しません。
import threading
from threading import current_thread
def wont_work():
threadLocal = threading.local() #oops, this creates a new dict each time!
initialized = getattr(threadLocal, 'initialized', None)
if initialized is None:
print("First time for", current_thread().name)
threadLocal.initialized = True
else:
print("Welcome back", current_thread().name)
wont_work(); wont_work()
このような出力になります。
First time for MainThread
First time for MainThread
マルチプロセッシングモジュール
グローバル変数はすべてスレッドローカルになります。
multiprocessing
モジュールは各スレッドに対して新しいプロセスを作成するからです。
この例を考えてみましょう。
processed
カウンターはスレッドローカルストレージの一例です。
from multiprocessing import Pool
from random import random
from time import sleep
import os
processed=0
def f(x):
sleep(random())
global processed
processed += 1
print("Processed by %s: %s" % (os.getpid(), processed))
return x*x
if __name__ == '__main__':
pool = Pool(processes=4)
print(pool.map(f, range(10)))
このように出力されます。
Processed by 7636: 1
Processed by 9144: 1
Processed by 5252: 1
Processed by 7636: 2
Processed by 6248: 1
Processed by 5252: 2
Processed by 6248: 2
Processed by 9144: 2
Processed by 7636: 3
Processed by 5252: 3
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
...もちろん、スレッドIDやそれぞれのカウント、順番は実行ごとに異なります。
関連
-
[解決済み] Pythonには文字列の'contains'サブストリングメソッドがありますか?
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] Pythonで2つのリストを連結する方法は?
-
[解決済み] Python 3で「1000000000000000 in range(1000000000000001)」はなぜ速いのですか?
-
[解決済み] Javaにおける "implements Runnable "と "extends Thread "の違いについて
-
[解決済み] モジュールの関数名(文字列)を使って、モジュールの関数を呼び出す。
-
[解決済み] プロセスとスレッドの違いは何ですか?
-
[解決済み】ネストされたディレクトリを安全に作成するには?
-
[解決済み】Pythonに三項条件演算子はありますか?
-
[解決済み] djangoフレームワークでフォームフィールドから値を取得するには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] PythonでのAWS Lambdaのインポートモジュールエラー
-
[解決済み] pandasのDataFrameから空のセルを含む行を削除する
-
[解決済み] Django Rest Framework ファイルアップロード
-
[解決済み] PythonからSMTPを使用してメールを送信する
-
[解決済み] スペースがないテキストを単語のリストに分割する方法
-
[解決済み] あるオブジェクトが数であるかどうかを確認する、最もパイソン的な方法は何でしょうか?
-
[解決済み] tensorflowのCPUのみのインストールでダイナミックライブラリ 'cudart64_101.dll' を読み込めなかった
-
[解決済み] subprocess.run()の出力を抑制またはキャプチャするには?
-
[解決済み] Pythonの文字列の前にあるbという接頭辞は何を意味するのですか?
-
[解決済み] Pythonの「スレッドローカルストレージ」とは何ですか、そしてなぜそれが必要なのですか?