Python websockets 服务器和 websockets 客户端在运行这两个任务时使用 asyncio 断言错误

Posted

技术标签:

【中文标题】Python websockets 服务器和 websockets 客户端在运行这两个任务时使用 asyncio 断言错误【英文标题】:Python websockets server and websockets client using asyncio assertion error when running both tasks 【发布时间】:2020-07-01 09:21:52 【问题描述】:

我有 3 台机器; A、B、C。

A 正在运行 C 想要连接的 websocket 服务器,但 C 无法直接连接到 A。为了解决这个问题,我想通过机器 B 来“代理”websocket。

A 充当发布者,每隔几秒就产生新的数据包,我想将这些数据包推送到 C。C 不需要向 A 发送任何内容(尽管将来可能需要)。

我想通过使用 websockets (https://pypi.org/project/websockets/) 模块来实现这个代理。我目前正在尝试在 B 上创建一个服务器来侦听连接并保持与任何客户端的 websocket 连接。然后我想异步运行一个连接到机器 A 的 websocket 客户端。这是一个订阅者连接,从 websocket 连接到 A 的任何更新都应该推送到 C(或连接到 B 的任何其他客户端)。

这是我当前(最小)的实现,其中发生了错误。

sockets = set()

def register(websocket):
    sockets.add(websocket)

def unregister(websocket):
    sockets.remove(websocket)

async def update_clients(update):
    if sockets:
        await asyncio.wait([socket.send(update) for socket in sockets])

async def client_server(websocket, path):
    register(websocket)
    await websocket.send("Welcome!")

async def live_updates():
    async with websockets.connect(LIVE_URL) as websocket:
        async for update in websocket.recv():
            await update_clients(update)

webserver = websockets.serve(client_server, "0.0.0.0", PORT)

loop = asyncio.get_event_loop()
loop.run_until_complete(webserver)
loop.run_until_complete(live_updates)
loop.run_forever()

报错如下

Traceback (most recent call last):
  File "/usr/lib/python3.6/asyncio/base_events.py", line 1310, in call_exception_handler
    self.default_exception_handler(context)
  File "/usr/lib/python3.6/asyncio/base_events.py", line 1282, in default_exception_handler
    value = repr(value)
  File "/usr/lib/python3.6/asyncio/base_tasks.py", line 15, in _task_repr_info
    coro = coroutines._format_coroutine(task._coro)
  File "/usr/lib/python3.6/asyncio/coroutines.py", line 276, in _format_coroutine
    assert iscoroutine(coro)
AssertionError

【问题讨论】:

【参考方案1】:

当我删除第二个run_until_complete(live_updates) 时,代码运行时没有错误。所以我删除了第一个run_until_complete,将我的代码与https://websockets.readthedocs.io/en/stable/intro.html 中的示例代码进行了比较,并意识到

run_until_complete(live_updates) 应该是run_until_complete(live_updates())

我会留下这个问题,以防有人遇到同样的错误,因为错误消息会让初学者感到困惑。

【讨论】:

如果机器 B 实际使用 Django Channels 运行 websocket,你知道如何实现相同的路由吗?基本上,我希望 Django Channels 服务器建立对上游服务器(在您的情况下为服务器 A)的一次性持久订阅,然后将所有后续传入数据从那里路由到 C。我已经习惯运行 Django Channels 消费者(websocket 服务器),但我想知道如何将 websocket 客户端组合到其中。

以上是关于Python websockets 服务器和 websockets 客户端在运行这两个任务时使用 asyncio 断言错误的主要内容,如果未能解决你的问题,请参考以下文章

webSocket那些事之socket.io

在 Websocket 通过 Nginx 转发用户 IP

如何停止 Python Websocket 客户端“ws.run_forever”

代理将 websockets 和 http 重定向到同一个(unix)套接字

WebSocket通信协议基础原理与潜在安全威胁

socket.io websocket