[英]Python websockets lib client persistent connection (with class implementation)
I'm trying to implement a websocket client in python using websockets
and the apparently mandatory asyncio
which I never used before (and I have a hard time to understand...).我正在尝试使用
websockets
和我以前从未使用过的明显强制性的asyncio
在 python 中实现一个 websocket 客户端(我很难理解......)。
I've read a lot on the subject and saw (too) many examples here and everywhere, but I can't find a way to properly make a websocket client with a persistent connection.我已经阅读了很多关于这个主题的文章,并且在这里和到处都看到了(太多)很多例子,但是我找不到一种方法来正确地制作一个具有持久连接的 websocket 客户端。
Here's what I have right now, based on examples I found here and there (with some obfuscated data) :这是我现在所拥有的,基于我在这里和那里找到的示例(带有一些混淆数据):
import json
import asyncio
from websockets import connect
URL = 'wss://server.com/endpoint'
class Websocket:
async def __aenter__(self):
self._conn = connect(URL)
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()
class Handler:
def __init__(self):
self.wws = Websocket()
self.loop = asyncio.get_event_loop()
def command(self, cmd):
return self.loop.run_until_complete(self.__async__command(cmd))
async def __async__command(self, cmd):
async with self.wws as echo:
await echo.send(json.dumps(cmd))
return await echo.receive()
def main():
handler = Handler()
foo = handler.command('authentication command')
print('auth: ', foo)
bar = handler.command('another command to run depending on the first authentication')
print('command: ', bar)
if __name__ == '__main__':
main()
Basically right now I get these answers (simplified and obfuscated) :基本上现在我得到这些答案(简化和混淆):
auth: Ok, authenticated
command: Command refused, not authenticated
I suppose my problem is that the block async with self.wws as echo:
kind of create the connection, runs its code then drop it instead of keeping the connection alive.我想我的问题是该块
async with self.wws as echo:
创建连接,运行其代码然后删除它而不是保持连接处于活动状态。 Since we are not using a usual __init__
here but some asyncio
voodoo I don't understand, I'm kind of stuck.由于我们在这里没有使用通常的
__init__
而是一些我不明白的asyncio
voodoo,我有点卡住了。
I think your diagnosis is correct, the problem is that the async context manager it creating and closing a connection for each call of Handler.command
... really not want you want.我认为您的诊断是正确的,问题是异步上下文管理器为每次
Handler.command
调用创建和关闭连接......真的不想要你想要的。
Instead you could just synchronously establish the websocket connection during the init of Handler
and then store the connection websocket (instance of type WebSocketClientProtocol
) as a class member for later use, as in this sample code:相反,您可以在
Handler
初始化期间同步建立 websocket 连接,然后将连接 websocket(类型为WebSocketClientProtocol
实例)存储为类成员以供以后使用,如以下示例代码所示:
import json
import asyncio
from websockets import connect
URL = 'ws://localhost:8000'
class Handler:
def __init__(self):
self.ws = None
self.loop = asyncio.get_event_loop()
# perform a synchronous connect
self.loop.run_until_complete(self.__async__connect())
async def __async__connect(self):
print("attempting connection to {}".format(URL))
# perform async connect, and store the connected WebSocketClientProtocol
# object, for later reuse for send & recv
self.ws = await connect(URL)
print("connected")
def command(self, cmd):
return self.loop.run_until_complete(self.__async__command(cmd))
async def __async__command(self, cmd):
await self.ws.send(json.dumps(cmd))
return await self.ws.recv()
def main():
handler = Handler()
foo = handler.command('authentication command')
print('auth: ', foo)
bar = handler.command('another command to run depending on the first authentication')
print('command: ', bar)
if __name__ == '__main__':
main()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.