3

テスト モジュール用の 2 つのスレッド「test_a」と「test_b」を起動するメイン スレッドがあるとします。両方のテスト モジュール スレッドは、テストの実行が終了したか、エラー、警告が発生したか、または他の情報を更新したいかどうかに関係なく、状態を維持します。

メインスレッドがこの情報にアクセスし、それに応じて動作する方法。たとえば、「test_a」がエラー フラグを立てた場合。「メイン」は、エラーが発生する前に残りのテストをどのように認識して停止しますか?

これを行う1つの方法は、グローバル変数を使用することですが、それは非常に醜いものになります..すぐに。

4

1 に答える 1

6

明らかな解決策は、コンストラクター/開始時にスレッドオブジェクト/関数に渡すことにより、ある種の可変変数を共有することです。

これを行う明確な方法は、適切なインスタンス属性を持つクラスを構築することです。単なるスレッド関数の代わりに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.Queueos.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.Poolmap_asyncAsyncResult

于 2013-05-21T18:54:02.547 に答える