如何以非阻塞方式从异步队列中消费?

时间:2017-12-10 14:23:01

标签: python tornado python-3.6 python-asyncio

我正在尝试使用tornado,websockets和asyncio.Queue

在Web应用程序中创建类似终端的功能

我现在被困在实现类似input函数的地方,其中协程暂停执行并等待用户输入内容

我的初步设计是为每个实现sendreceivenext方法的用户创建会话对象

  • send方法用于向用户发送消息
  • receive方法接收用户消息并将其重定向到处理程序
  • next方法暂停执行处理程序直到下一个用户消息

会话班:

import asyncio

class Session:
    def __init__(self, ws_handler):
        self.ws_handler = ws_handler
        self.cbs = list()
        self.q = asyncio.Queue()
        self.waiting = False

    async def consume(self):
        return await self.q.get()

    async def next(self):
        self.waiting = True
        return await self.consume()

    def send(self, response):
        self.ws_handler.write_message(response.bytes())

    async def receive(self, msg):
        if self.waiting:
            await self.q.put(msg)
            self.waiting = False
            return
        await views.authenticate(self, msg)
        for cb in self.cbs:
            print('calling', cb.__name__)
            await cb(self, msg)

    def register(self, *callbackss):
        self.cbs += list(*callbackss)

并且愚蠢到我以为我可以像这样使用它:

async def handle_input(some_message):
    session.send("Please enter your name")
    name = await session.next()
    # do some stuff

这实际上是以handle_input按预期暂停的方式工作,但当然整个服务器都被永久阻止。

我的问题是如何正确使用àsyncio.Queue或任何其他策略来实现input类似功能

我正在使用python 3.6和tornado 3.5.2

1 个答案:

答案 0 :(得分:0)

更新: asynctio.Queue不适用于Tornado的事件循环。这就是为什么你得到阻止行为。见the issue我打开了这个。

你现在有两个选择:

  1. 使用tornado.queues.Queue代替asyncio.Queue
  2. 或者使用asyncio的事件循环而不是Tornado的事件循环。见docs