如何在一个类中实现 asyncio websockets?
Posted
技术标签:
【中文标题】如何在一个类中实现 asyncio websockets?【英文标题】:How can I implement asyncio websockets in a class? 【发布时间】:2016-09-19 02:03:58 【问题描述】:我想通过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!"
【问题讨论】:
【参考方案1】:如何编写异步程序?
-
你应该用
async
定义异步函数
您应该调用 async
功能与await
你需要event loop 来启动你的异步程序
所有其他几乎与常规 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://***.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())
您可以在docs 中找到许多使用websockets
的示例。
【讨论】:
收到回复后关闭。它怎么会继续接收消息? @FeedTheWeb 只是在上下文管理器中不断接收回复。 @MikhailGerasimov 我不明白上面的评论。您如何确保脚本不会在一次回复后结束?谢谢 @HJA24 如果你想不断地发送/接收数据,你通常启动一个服务器。例如,查看a code snippet here,特别是server.serve_forever()
行。启动服务器的具体方法取决于您要实现的目标。用于启动与 asyncio 一起使用的服务器的流行高级库是 aiohttp。它提供了一种使用多种协议的方法including websockets。
@MikhailGerasimov 嗨,我正在关注不同来源的文档,他们不使用 server.serve.forever()
,所以我有点困惑。你能看看我关于 SO ***.com/questions/61216022/… 的问题吗以上是关于如何在一个类中实现 asyncio websockets?的主要内容,如果未能解决你的问题,请参考以下文章
如何在另一个类中的 JPanel 类中实现 ActionListener?