Python websockets lib 客户端持久连接(带类实现) [英] Python websockets lib client persistent connection (with class implementation)
问题描述
我正在尝试使用 websockets
和我以前从未使用过的明显强制性的 asyncio
在 python 中实现一个 websocket 客户端(我很难理解...).
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...).
我已经阅读了很多关于这个主题的文章,并且在这里和到处都看到了(太多)很多例子,但我找不到一种方法来正确地制作一个具有持久连接的 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.
- 我需要一个持久连接,因为需要在同一个连接上请求命令,第一个是身份验证命令.
- 远程服务器是我无法控制的第 3 方 API.
- 我想我可以在程序发送的每个命令的同时运行一个身份验证请求,但是对于每个命令打开 > auth > request > close 而不是在整个程序的生命周期中保持一个连接处于活动状态,这感觉不对
- 我的实现是一个使用许多类的库,我需要将 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
我想我的问题是块 async with self.wws as echo:
有点创建连接,运行它的代码然后删除它而不是保持连接活动.由于我们在这里没有使用通常的 __init__
而是一些 asyncio
巫术,我不明白,我有点卡住了.
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. Since we are not using a usual __init__
here but some asyncio
voodoo I don't understand, I'm kind of stuck.
推荐答案
我认为你的诊断是正确的,问题是异步上下文管理器为 Handler.command
的每次调用创建和关闭连接代码> ...真的不想要你想要的.
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
初始化期间同步建立 websocket 连接,然后将连接 websocket(类型为 WebSocketClientProtocol
的实例)存储为类成员以备后用,如本示例代码所示:
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:
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()
这篇关于Python websockets lib 客户端持久连接(带类实现)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!