Pythonでのイベント駆動の基本:select文の使い方

Python
この記事は約6分で読めます。
スポンサーリンク

プログラム解説

まず、Thread1 をServer Thread2をClientとして立ちあげて、Thread1 と Thread2 両方で、データを受信したら応答としてデータを送信するようにしてあります。
そして、Thread2 側では、通信のきっかけを与えるために、Timerを起動して1秒後にデータを送信しています。

##マルチスレッド・Socket通信・タイマーを使っていますが、以前の記事で紹介していますので そもそも マルチスレッド・Socket通信 。タイマーてどう使うの?って方は以下を確認ください。

マルチスレッド

Socket通信

タイマー

スポンサーリンク

Select使い方解説

Selectの関係部分を抜き出してして、以下に記述します。

import select

    fd_set = set()
    fd_set.add(con)

    while True:
	    r, w, x = select.select(list(fd_set), [], [], 10)
	    for fd in r:
	        data = fd.recv(1024) 
	        print(data)
	        time.sleep(0.1)
	        snd = bytearray([1, 2, 3, 4])
	        fd.send( snd )

まず、selectを使用するためにライブラリをインポートします。
以下です。標準ライブラリですので、何も考えずに以下をインポートしてください。

import select

続いて、selectに与えるリストを生成します。

    fd_set = set()            # インスタンスを取得
    fd_set.add(con)           # 受信したソケットをセット

複数取得したい場合は、 fd_set.add( )を複数回呼べば登録可能です。

続いて、肝心のSelect関数です。以下のように記載すれば複数のIO入力を待ってくれます。
※Select自体は同期関数ですので、イベントとして処理したいものはすべてここに登録してください。

第1引数に先ほど生成したリスト第4引数にタイムアウト時間を設定してください。
※第2と第3の引数の使い方は、すいません詳しくは知りません。。。多分、Write完了となにかだと思います。

r, w, x = select.select(list(fd_set), [], [], 10)

そして、以下のようにfor文でループさせれば、イベントが発生したものをfdに引き渡ししてくれますので、そのままrecv()やsend()を呼び出せば使用できます。

for fd in r:
    fd.recv()
    fd.send(data)

実行結果

では、本コードの実行結果です。

出力されているデータとしては以下の通りで、それぞれ正しくデータを受信して送信できることを確認できました。

b’\x05\x06\x07\x08’というのがタイマコールバックから送信
b’\x01\x02\x03\x04’がThread1からの送信(Thread1が受信したことをトリガに送信)
b’\t\n\x0b\x0c’が Thread2からの送信 (Thread2が受信したことをトリガに送信)

スポンサーリンク

まとめ

ちょっと、Selectを使用するまでにひと手間あったり、Select受信あとにひと手間いりますが、結構簡単にイベント駆動っぽい処理ができるようになりました。

複雑な処理を使用とすればするほど、こういった知識が重要になってくると思いますので、みなさんも使い方を覚えて使用してみてください。

Pythonについて勉強したい人は以下がおすすめです。私も持っていてたまに眺めて勉強していますものですのでぜひ購入して学習してみてください。

コメント

タイトルとURLをコピーしました