Python でのマルチスレッドの処理は threading.Event で wait2021年05月12日 11時22分47秒

Python でも結構スレッドを多用する。利用するライブラリがスレッドを生成して利用することを前提にしていることが多い。大体、通信系のライブラリでブロックし、読み込まれたメッセージ単位で処理するライブラリとして実装されている事が多い。

そんなライブラリを使うときに厄介なのが、終了処理の伝達。各スレッドに終了をしっかりと伝えないといけない。幾つかの型を試したが、threading ライブラリの Event クラスを使うのが一番感じが良さそうだった。終了通知まで待機のスレッドだと、wait() 関数で待機。もし、定期的に起きて処理する事項があるのなら、タイムアウトを指定して。

Event をメイン関数か処理の基軸で生成し、各々の Thread に渡していく。

% cat event_loop.py 
#!/usr/local/bin/python3.7

import threading
import time

def func( evt ):
    time.sleep( 5 )
    print( "wakeup" )
    evt.set()

event = threading.Event()
thread = threading.Thread( target = func, args = ( event, ) )
thread.start()
while not event.wait( 1 ):
    print( "." )
print( "done" )
この例では、メインスレッドは 1 秒後とに進捗を表示する。wait() 関数は、時間切れで返ると偽を返し、event.set() が呼ばれて返ると真を返す。つまり、待機中は常に . を表示することになる。

ここでの例では使わなかったが is_set() 関数が存在し、set() が呼ばれたかを調べることも出来るが、is_set() でループを作ると別途 time.sleep が必要になって、冗長になってしまう。

% python3.7 event_loop.py   
.
.
.
.
wakeup
done
実行結果はこちら。