Skip to main content
 首页 » 编程设计

python之无法在类内发送 websockets 消息

2024年09月03日42leader

我打算编写一个类 WebsocketHandler 来包装包 websockets

这是代码:

import asyncio 
import websockets 
 
 
class WebsocketHandler: 
    __connection = None 
 
    def __init__(self): 
        asyncio.run(self.__setConnection()) 
 
    async def __setConnection(self): 
        async with websockets.connect("ws://localhost/your/path") as websocket: 
            self.__connection = websocket 
            print("Connected") 
 
    def send(self, msg): 
        self.__connection.send(msg) 
        print("message Send") 
 
 
ws = WebsocketHandler() 
ws.send("message") 
 

对于服务器部分,我有另一个完成的脚本可以工作(使用其他语言的其他脚本进行测试),当我有新连接、收到消息和客户端断开连接时,它会向我发送消息。

当我尝试它时,脚本成功连接到我的 websocket 服务器(脚本打印 Connected 并且在服务器端我获得了一个新连接)。

然后我在脚本中收到警告

RuntimeWarning: coroutine 'WebSocketCommonProtocol.send' was never awaited  
self.__connection.send(msg) 

然后我的脚本打印 Message send 并停止。

问题是,在服务器端,我没有收到消息,只有一条消息告诉我客户端已断开连接。脚本基本上不会发送消息,也不会产生错误。

有人知道问题出在哪里吗?

请您参考如下方法:

问题是 WebsocketHandler 类只有一个异步方法,即 __setConnection,它是通过调用 asyncio.run 来运行的功能。 docs这么说

This function always creates a new event loop and closes it at the end.

也就是说,这是唯一可以运行异步代码的地方。您的代码创建一个 websocket 连接并在打印“已连接”后立即将其关闭。发生这种情况是因为您使用 async with 调用 websockets.connect 方法作为异步上下文管理器,它会在退出时自动关闭连接。这是第一个缺陷,第二个是 self.__connection.send 函数是一个 coroutine 并且它不会运行,直到你 await 就可以了。这正是错误消息告诉您的内容。以下是修复 websocket 处理程序类的方法:

import asyncio 
import websockets 
 
 
class WebsocketHandler(object): 
 
    def __init__(self): 
        self.conn = None 
 
    async def connect(self, url): 
        self.conn = await websockets.connect(url) 
 
    async def send(self, msg): 
        await self.conn.send(msg) 
 
    async def close(self): 
        await self.conn.close() 
 
 
async def main(): 
    handler = WebsocketHandler() 
    await handler.connect('ws://localhost:8765') 
 
    await handler.send('hello') 
    await handler.send('world') 
 
    await handler.close() 
 
 
loop = asyncio.get_event_loop() 
loop.run_until_complete(main())