Python threading入門
はじめに
pythonのthreadingを使った並行処理を実装して見ましょう。
本記事ではスレッドを使うことで20秒かかる処理を10秒に短縮します。
20秒かかる処理
次のスクリプトを実行すると20秒程度かかると思います。関数f1、f2の処理にそれぞれ10秒かかるので
- f1を実行する
- f2を実行する
というように順次処理を行うため、合計20秒かかってしまいます。
sample.pyCopied!!import time def f1(): for i in range(10): print(f"f1 index={i}") time.sleep(1) def f2(): for i in range(5): print(f"f2 index={i}") time.sleep(2) def main(): startTime = time.time() f1() f2() endTime = time.time() print(f"処理時間:{endTime-startTime}秒") if __name__ == "__main__": main()
スレッドを使って処理時間を短縮しよう
-
threadingモジュールをimportします
Copied!!import threading
-
スレッドで実行したい関数を引数targetに渡します
Copied!!threads = [ threading.Thread(target=f1), threading.Thread(target=f2), ]
-
startでスレッドの処理を開始します
Copied!!for t in threads: t.start()
-
joinでスレッドの処理が完了するのを待ちます
Copied!!for t in threads: t.join()
-
完成形
thread.pyCopied!!import threading import time def f1(): for i in range(10): print(f"f1 index={i}") time.sleep(1) def f2(): for i in range(5): print(f"f2 index={i}") time.sleep(2) def main(): threads = [ threading.Thread(target=f1), threading.Thread(target=f2), ] startTime = time.time() for t in threads: t.start() for t in threads: t.join() endTime = time.time() print(f"処理時間:{endTime-startTime}秒") if __name__ == "__main__": main()
なぜ実行時間を短縮できるのか
thread.pyを実行すると10秒程度で処理が終了したと思います。
Copied!!$ python3 thread.py f1 index=0 f2 index=0 f1 index=1 f2 index=1 f1 index=2 f1 index=3 f2 index=2 f1 index=4 f1 index=5 f2 index=3 f1 index=6 f1 index=7 f2 index=4 f1 index=8 f1 index=9 処理時間:10.012817621231079秒
スレッドを使うとf1とf2の処理は交互に実行されます。上のログを見ると次のような順番で関数f1、f2が実行されたことがわかります。
- f1のfor文の1周目を実行。
- f2のfor文の1周目を実行。
- f1のfor文の2周目を実行。
- f2のfor文の2周目を実行。
これより、f1のsleepで指定した時間を待たずにf2が実行され、また、f1はf2のsleepの影響を受けずに処理を進めていることがわかります。つまり、f1とf2をそれぞれ並行して実行しているため、処理時間を10秒程度に短縮することができています。
まとめ
本記事ではスレッドを使った並行処理について紹介しました。スレッドを使うことでスクリプトの実行時間を短縮できることを直に感じていただけたかと思います。