明らかな解決策は、コンストラクター/開始時にスレッドオブジェクト/関数に渡すことにより、ある種の可変変数を共有することです。
これを行う明確な方法は、適切なインスタンス属性を持つクラスを構築することです。単なるスレッド関数の代わりにthreading.Thread
subclassを使用している場合、通常はサブクラス自体をそれらの属性を固定する場所として使用できます。しかし、list
それが短いという理由だけでそれを示します:
def test_a_func(thread_state):
# ...
thread_state[0] = my_error_state
# ...
def main_thread():
test_states = [None]
test_a = threading.Thread(target=test_a_func, args=(test_states,))
test_a.start()
Lock
またはCondition
を変更可能な状態オブジェクトにパックすることもできます (通常はそうしたい)ため、 と の間main_thread
で適切に同期できますtest_a
。
(別のオプションはqueue.Queue
、os.pipe
、 などを使用して情報を渡すことですが、そのキューまたはパイプを子スレッドに取得する必要があります。これは、上記とまったく同じ方法で行います。)
ただし、本当にこれを行う必要があるかどうかを検討する価値があります。とを「スレッド関数」ではなく「ジョブ」と考えると、test_a
これらのジョブをプールで実行し、結果やエラーの受け渡しをプールに処理させることができます。test_b
例えば:
try:
with concurrent.futures.ThreadPoolExecutor(workers=2) as executor:
tests = [executor.submit(job) for job in (test_a, test_b)]
for test in concurrent.futures.as_completed(tests):
result = test.result()
except Exception as e:
# do stuff
ここで、test_a
関数が例外を発生させると、メイン スレッドがその例外を受け取ります。これは、with
ブロックを終了することを意味し、他のすべてのジョブがキャンセルされて破棄され、ワーカー スレッドがシャットダウンするためです。
2.5-3.1 を使用している場合、組み込みはありませんが、バックポートを PyPI オフにconcurrent.futures
インストールするか、周りを書き直すことができます。(一連のジョブを作成し、オブジェクトの反復子を取得するために呼び出しを行う必要があるため、その方法は少し複雑になりますが、それでもかなり単純です。)multiprocessing.dummy.Pool
map_async
AsyncResult