背景
PythonでSocketIO通信を行う必要があったため、今後の開発の効率化のためにSocketIO通信を行うクラスのテンプレートを作成する。
記事の目的
PythonでSocketIOクライアントを作成する
python-socketio
python-socketioを使用したSocketIOクライアントを作成する
選定理由
python-socketioの選定理由は、下記の通りである。導入方法
python-socketioの導入手順は、下記の通りである。- pipを利用して必要なライブラリをインストールする
$ pip install requests python-socketio
テンプレート
python-socketioの使用テンプレートは、下記の通りである。# socketioライブラリのインポート
import socketio
# ログ出力用ライブラリのインポート
from logging import getLogger, StreamHandler, DEBUG, INFO, ERROR
# 時間関係ライブラリのインポート
import time
# 終了シグナルをキャッチするライブラリのインポート
import signal
# マルチスレッドライブラリのインポート
import threading
# ロガーのインスタンス作成
logger = getLogger(__name__)
stream_handler = StreamHandler()
# ログレベルを設定
log_level = INFO
logger.setLevel(log_level)
stream_handler.setLevel(log_level)
# ロガーにハンドラーをセット
logger.addHandler(stream_handler)
# SocketIOのテンプレート
class SocketIOClient:
# namespaceの設定用クラス
class NamespaceClass(socketio.ClientNamespace):
def on_connect(self):
pass
def on_disconnect(self):
pass
def on_message(self, data):
pass
def on_server_to_client(self, data):
pass
# 接続時に呼ばれるイベント
def on_connect(self):
logger.info('Connected to server (%s:%d, namespace="%s", query="%s")',\
self.ip_,self.port_,self.namespace_,self.query_)
self.is_connect_ = True
# 切断時に呼ばれるイベント
def on_disconnect(self):
logger.info('Disconnected from server (%s:%d, namespace="%s", query="%s")',\
self.ip_,self.port_,self.namespace_,self.query_)
self.is_connect_ = False
def on_message(self, data):
logger.info('Received message %s', str(data))
# サーバーからイベント名「server_to_client」でデータがemitされた時に呼ばれる
def on_server_to_client(self, data):
logger.info('Received message %s', str(data))
# Namespaceクラス内の各イベントをオーバーライド
def overload_event(self):
self.Namespace.on_connect = self.on_connect
self.Namespace.on_disconnect = self.on_disconnect
self.Namespace.on_message = self.on_message
self.Namespace.on_server_to_client = self.on_server_to_client
# 初期化
def __init__(self,ip,port,namespace,query):
self.ip_ = ip
self.port_ = port
self.namespace_ = namespace
self.query_ = query
self.is_connect_ = False
self.sio_ = socketio.Client()
self.Namespace = self.NamespaceClass(self.namespace_)
self.overload_event()
self.sio_.register_namespace(self.Namespace)
# 接続確認
def isConnect(self):
return self.is_connect_
# 接続
def connect(self):
# 接続先のURLとqueryの設定
url = 'ws://'+self.ip_+':'+str(self.port_)+'?query='+self.query_
logger.info('Try to connect to server(%s:%d, namespace="%s", query="%s")',\
self.ip_,self.port_,self.namespace_,self.query_)
try:
self.sio_.connect(url, namespaces=self.namespace_)
except:
logger.error('Cannot connect to server(%s:%d, namespace="%s", query="%s")',\
self.ip_,self.port_,self.namespace_,self.query_)
else:
if not self.is_connect_:
logger.error('Namespace may be invalid.(namespace="%s")',\
self.namespace_)
# 切断
def disconnect(self):
try:
self.sio_.disconnect()
except:
logger.error('Cannot disconnect from server(%s:%d, namespace="%s", query="%s")',\
self.ip_,self.port_,self.namespace_,self.query_)
else:
self.is_connect_ = False
# 再接続
def reconnect(self):
self.disconnect()
time.sleep(5)
self.connect()
# クライアントからデータ送信(send)する
def sendData(self, data):
try:
self.sio_.send(data, namespace=self.namespace_)
except:
logger.error('Has not connected to server(%s:%d, namespace="%s", query="%s")',\
self.ip_,self.port_,self.namespace_,self.query_)
else:
logger.info('Send message %s (namespace="%s")', str(data), self.namespace_)
# 独自定義のイベント名「client_to_server」で、クライアントからデータ送信(emit)する
def emitData(self, data):
try:
self.sio_.emit('client_to_server', data, namespace=self.namespace_)
except:
logger.error('Has not connected to server(%s:%d, namespace="%s", query="%s")',\
self.ip_,self.port_,self.namespace_,self.query_)
else:
logger.info('Emit message %s (namespace="%s")', \
str(data), self.namespace_)
# メインの処理
def run(self):
while True:
self.connect()
time.sleep(1)
if self.is_connect_:
break
p = threading.Thread(target=self.sio_.wait)
p.setDaemon(True)
p.start()
if __name__ == '__main__':
# Ctrl + C (SIGINT) で終了
signal.signal(signal.SIGINT, signal.SIG_DFL)
# SocketIO Client インスタンスを生成
sio_client = SocketIOClient('localhost', 10000, '/test', 'secret')
# SocketIO Client インスタンスを実行
sio_client.run()
# データを送信
for i in range(10):
sio_client.sendData({'test_data': 'send_from_client'})
sio_client.emitData({'test_data': 'emit_from_client'})
time.sleep(1)
# 切断
sio_client.disconnect()
logger.info('Finish')
# 終了
exit()
備考
- namespaceは、必ず「/」(スラッシュ)から始まる必要がある
- 上記テンプレートは、サーバーと通信テストができる
まとめ
- Python-SocketIOを利用したクライアントモジュールを作成した
参考文献
変更履歴
- 2019/08/17: 新規作成
0 件のコメント:
コメントを投稿