asyncio
およびwebsockets
を介して、以下に示す形式でWebSocketに接続したいと思います。どうすればこれを達成できますか?
from websockets import connect
class EchoWebsocket:
def __init__(self):
self.websocket = self._connect()
def _connect(self):
return connect("wss://echo.websocket.org")
def send(self, message):
self.websocket.send(message)
def receive(self):
return self.websocket.recv()
echo = EchoWebsocket()
echo.send("Hello!")
print(echo.receive()) # "Hello!"
非同期プログラムの書き方は?
async
で非同期関数を定義する必要がありますawait
で非同期関数を呼び出す必要がありますその他はすべて、通常のPythonプログラムと同じです。
import asyncio
from websockets import connect
class EchoWebsocket:
async def __aenter__(self):
self._conn = connect("wss://echo.websocket.org")
self.websocket = await self._conn.__aenter__()
return self
async def __aexit__(self, *args, **kwargs):
await self._conn.__aexit__(*args, **kwargs)
async def send(self, message):
await self.websocket.send(message)
async def receive(self):
return await self.websocket.recv()
async def main():
async with EchoWebsocket() as echo:
await echo.send("Hello!")
print(await echo.receive()) # "Hello!"
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
出力:
Hello!
ご覧のとおり、コードは作成したものとほとんど同じです。
唯一の違いは、websockets.connect
は非同期コンテキストマネージャとして設計されていることです(__aenter__
、__aexit__
を使用します)。接続を解放する必要があり、クラスの初期化中に非同期操作を行うのにも役立ちます(__init__
の非同期バージョンがないため)。
同じ方法でクラスを編成することをお勧めします。しかし、なんらかの理由でコンテキストマネージャーを使用したくない場合は、新しい__await__
メソッドを使用して非同期の初期化を行い、その他の非同期関数を使用して接続を解放できます。
import sys
import asyncio
from websockets import connect
class EchoWebsocket:
def __await__(self):
# see: http://stackoverflow.com/a/33420721/1113207
return self._async_init().__await__()
async def _async_init(self):
self._conn = connect("wss://echo.websocket.org")
self.websocket = await self._conn.__aenter__()
return self
async def close(self):
await self._conn.__aexit__(*sys.exc_info())
async def send(self, message):
await self.websocket.send(message)
async def receive(self):
return await self.websocket.recv()
async def main():
echo = await EchoWebsocket()
try:
await echo.send("Hello!")
print(await echo.receive()) # "Hello!"
finally:
await echo.close()
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
websockets
の使用例の多くは docs にあります。