Pythonのthreadingを用いて、スレッド数の上限の範囲内で関数を並行処理し、戻り値を順々に得ていく

実現したいこと

(1)Pythonのthreadingモジュールを使用し、並行処理の最大数を設定しつつ関数の実行終了時に戻り値を得る。
(2)スレッドを何度も立て直すことなく、スレッド待機し続けながら(1)を実現する。

(1)だけでも方法を教えていただきたいです。

前提

Pythonでスレッド数の上限を制限しつつ関数の並行処理を行い、終了したものが発生次第、再び実行するプログラムを書いています。
並行処理したい関数をfunc、list1から順々に取り出した引数をnumとして、最終的にやりたいことは下のようなイメージです。
(簡略化したイメージであり、実際のコードでは数値型のnum及びproc=subprocess.Popen("external.exe",stdin=subprocess.PIPE,stdout=subprocess.PIPE)が関数の引数で、関数内でprocを使って外部プログラムとのやり取りを行う奇異な構成になっています。)

スレッド数上限=3
list1=[1,2,3,5,8,10,12,15,16,19,20]

thread1:func(num=1)を実行開始
thread2:func(num=2)を実行開始
thread3:func(num=3)を実行開始(スレッド数上限3に到達)

thread3:func(num=3)終了、戻り値と終了したスレッドの番号3を得る

thread3:func(num=5)を実行開始

thread1:func(num=1)終了、戻り値と終了したスレッドの番号1を得る

thread1:func(num=8)を実行開始

thread3:func(num=5)終了、戻り値と終了したスレッドの番号3を得る

thread3:func(num=10)を実行開始

thread2:func(num=2)終了、戻り値と終了したスレッドの番号2を得る

thread2:func(num=12)を実行開始

発生している問題・エラーメッセージ

似たような事をやっている例を発見したので、https://teratail.com/questions/49684
https://superfastpython.com/thread-semaphore/
などを参考にしてコードを書いたのですが、関数の実行が終了したものから順番に戻り値と終了したスレッドの番号を得る方法が分かりません。書いたコードは一応戻り値を得ることができていますが、コードの見た目通り並行処理になっていません。
また、スレッドを何度も立て直すのも非効率だと思うので、スレッドを待機したまま上記のことを実現することはできないのでしょうか?

threadingの公式ドキュメントはこちらです
https://docs.python.org/ja/3/library/threading.html

該当のソースコード

Python

1import threading 2import queue 3import random 4import time 5 6def usigame(sem,num,q):7 with sem:8 print(f'{num}開始')9 time.sleep(random.uniform(0,3))10 print(f'{num}終了')11 q.put(num**2)12 13def main():14 sem = threading.Semaphore(3)15 q1 = queue.Queue()16 17 list1=[1,2,3,5,8,10,12,15,16,19,20]18 19 for num in list1:20 th = threading.Thread(target=usigame, args=(sem,num,q1))21 th.start()22 result=q1.get()23 print(result)24 25if __name__ == "__main__":26 main()

補足情報(FW/ツールのバージョンなど)

windows11環境です。

コメントを投稿

0 コメント