与 Quart 中的 websockets 双向通信
Bidirectional communiation with websockets in Quart
我希望能够在 Quart 中使用 WebSocket 来接收发送的任何消息,并发送我可能需要发送的任何消息。无法保证消息会在发送和接收之间交替。
例如,Quart's tutorial page on WebSockets 包含以下代码段:
@app.websocket('/api/v2/ws')
@collect_websocket
async def ws(queue):
while True:
data = await queue.get()
await websocket.send(data)
不知何故,我想修改while True
循环中的代码,以便我可以检查是否有任何数据要接收,但如果没有,我将改为检查队列。
我希望只有在有东西要接收时才能等待在套接字上接收(如果 receive
方法中有一个 timeout
参数,这也许可以实现),但这不是一个选择。
那么,我怎样才能 await
用于更新的 WebSocket 同时还 await
用于更新的其他东西?
Quart 的作者在 post Websockets in Quart 中回答了这个问题,其中包含一个片段,我对其稍作修改以获得以下内容:
import asyncio
from quart import copy_current_websocket_context, Quart, websocket
app = Quart(__name__)
@app.websocket('/ws')
async def ws():
async def consumer():
while True:
data = await websocket.receive()
async def producer():
while True:
await asyncio.sleep(1)
await websocket.send(b'Message')
consumer_task = asyncio.ensure_future(consumer())
producer_task = asyncio.ensure_future(producer())
try:
await asyncio.gather(consumer_task, producer_task)
finally:
consumer_task.cancel()
producer_task.cancel()
该代码片段创建了两个不同的异步函数,它们各自具有 while True
循环。然后,Python 的 asyncio.ensure_future
is used to create two different Task
继续工作。最后,调用 asyncio.gather
对任务进行并发评估。
通过在 ws
的定义中定义这两个任务,它们充当闭包,这意味着它们可以访问 websocket
"special" 全局对象,该对象仅在ws
函数。如果你想在 ws
函数体之外定义这些函数,也许是因为你需要从其他地方调用它们,你可以在将它们传递给 ensure_future
时使用 Quart 中的 copy_current_websocket_context
函数:
consumer_task = asyncio.ensure_future(
copy_current_websocket_context(consumer)()
)
我希望能够在 Quart 中使用 WebSocket 来接收发送的任何消息,并发送我可能需要发送的任何消息。无法保证消息会在发送和接收之间交替。
例如,Quart's tutorial page on WebSockets 包含以下代码段:
@app.websocket('/api/v2/ws')
@collect_websocket
async def ws(queue):
while True:
data = await queue.get()
await websocket.send(data)
不知何故,我想修改while True
循环中的代码,以便我可以检查是否有任何数据要接收,但如果没有,我将改为检查队列。
我希望只有在有东西要接收时才能等待在套接字上接收(如果 receive
方法中有一个 timeout
参数,这也许可以实现),但这不是一个选择。
那么,我怎样才能 await
用于更新的 WebSocket 同时还 await
用于更新的其他东西?
Quart 的作者在 post Websockets in Quart 中回答了这个问题,其中包含一个片段,我对其稍作修改以获得以下内容:
import asyncio
from quart import copy_current_websocket_context, Quart, websocket
app = Quart(__name__)
@app.websocket('/ws')
async def ws():
async def consumer():
while True:
data = await websocket.receive()
async def producer():
while True:
await asyncio.sleep(1)
await websocket.send(b'Message')
consumer_task = asyncio.ensure_future(consumer())
producer_task = asyncio.ensure_future(producer())
try:
await asyncio.gather(consumer_task, producer_task)
finally:
consumer_task.cancel()
producer_task.cancel()
该代码片段创建了两个不同的异步函数,它们各自具有 while True
循环。然后,Python 的 asyncio.ensure_future
is used to create two different Task
继续工作。最后,调用 asyncio.gather
对任务进行并发评估。
通过在 ws
的定义中定义这两个任务,它们充当闭包,这意味着它们可以访问 websocket
"special" 全局对象,该对象仅在ws
函数。如果你想在 ws
函数体之外定义这些函数,也许是因为你需要从其他地方调用它们,你可以在将它们传递给 ensure_future
时使用 Quart 中的 copy_current_websocket_context
函数:
consumer_task = asyncio.ensure_future(
copy_current_websocket_context(consumer)()
)