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

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

私は普段組み込みシステムのエンジニアです。

RTOSを使った組み込みシステムを開発しているとOSの機能を使って、イベント駆動アプリを制作するのが一般的です。

ですが、PythonではLinux等のように基本的に同期関数となっていて、一つのスレッドで複数のイベントを受け付けるのが標準のAPIでは実装しずらくなっています。

同期関数とは、呼び出したらその中が完了するまで処理が返ってこない関数のことです。

例としていうのであれば、Socket関数のrecv関数等がそういう作りになっています。

こういったことを解決するために、LinuxではSelect関数を使って、複数のIO入力を取得する方法があります。

そして、実はPythonにもSelectライブラリが組み込まれていて、同じような使い方ができるようになっているんです。

Select文サンプルコード

ですので、今回はPythonでのSelect文の使い方を紹介します。

では、まずいつも通りコードの全体をまず記載します。

import time
import threading
import socket
import select

Portnum = 12345
stop_application = False

def create_server(ip,port):
    server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server.bind( (ip,port) )
    server.listen()
    return server


def create_client(ip,port):
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect( (ip,port) )
    return client


def tm_callback( con ):
    if stop_application == False:
        snd = bytearray([5, 6, 7, 8])
        con.send( snd )


def th1_func():
    global stop_application
    server = create_server('127.0.0.1',Portnum)
    (con, client) = server.accept()
    
    fd_set = set()
    fd_set.add(con)
    
    while True:
        try:
            if stop_application == False:
                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 )
            else:
                con.close()
                break
        except:
            con.close()
            break

def th2_func():
    global stop_application
    
    con = create_client('127.0.0.1',Portnum)
    
    fd_set = set()
    fd_set.add(con)
    
    tm = threading.Timer( 1 , tm_callback,args=[con,]  )
    tm.start()
    
    while True:
        try:
            if stop_application == False:
                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([9, 10, 11, 12])
                    fd.send( snd )
            else:
                con.close()
                break
        except:
            con.close()
            break

def main_func( ):
    global stop_application
    thread1 = threading.Thread(target=th1_func)
    thread1.start()

    thread2 = threading.Thread(target=th2_func)
    thread2.start()
    
    while True:
        try:
            time.sleep(1)
        except KeyboardInterrupt:
            print("stop")
            stop_application = True
            thread1.join()
            thread2.join()
            break
    
if __name__ == '__main__':
	result = main_func() 

続いてはプログラムの解説ですが、解説は次ページにて記載します。

スポンサーリンク

コメント

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