简体   繁体   English

为什么asyncio.queue失败?

[英]why asyncio.queue get faild?

Python3, asyncio Task A is putting a number to a queue every 2s, task B is wait for the queue.get() with timeout 1s in a forever loop. Python3,asyncio任务A每2秒将一个数字放入队列,任务B在永久循环中等待超时为1的queue.get()。

I don't know why can't get the number from the queue in task B, if timeout is bigger than 2s, queue.get() is ok. 我不知道为什么不能从任务B的队列中获取数字,如果超时大于2s,queue.get()可以。

import asyncio


class Test:
    def __init__(self, loop=None):
        self._queue = asyncio.Queue(loop=loop)
        self._future = asyncio.Future(loop=loop)

    @asyncio.coroutine
    def run(self):
        asyncio.async(self._feed_queue(2))
        asyncio.async(self._recv())
        # yield from asyncio.sleep(10.0)
        # self._future.set_exception('Fail')

    @asyncio.coroutine
    def _feed_queue(self, interval):
        v = 0
        while True:
            yield from asyncio.sleep(interval)
            print("feed")
            yield from self._queue.put(v)
            v = v+1


    @asyncio.coroutine
    def _recv(self):
        while True:
            try:
                print('wait')
                # r = yield from asyncio.wait([self._queue.get(), self._future], return_when=asyncio.FIRST_COMPLETED, timeout=1.0)
                # for x in r[0]:
                #     if x.exception():
                #         raise x.exception()
                #     print("recv", x.result())

                try:
                    r = yield from asyncio.wait_for(self._queue.get(), timeout=1.0)
                    print(r)
                except:
                    continue
                # print("recv", r)
                # in done set
            except BaseException as e:
                print(e)
                break

        print("quit")


loop = asyncio.get_event_loop()
t = Test(loop=loop)
asyncio.async(t.run())
loop.run_forever()

output: 输出:

wait
wait
feed
wait
wait
feed
wait
wait
feed
wait

The first call to self._queue.get() may return the value, but it is not used, and new call is made. 首次调用self._queue.get()可能会返回该值,但不会使用该值,并且会进行新的调用。

Adjusted to use the call (and to use asyncio.ensure_future ; otherwise, AssertionError("yield from wasn't used with future",) is raised) 调整为使用调用(并使用asyncio.ensure_future ;否则, asyncio.ensure_future AssertionError("yield from wasn't used with future",)

@asyncio.coroutine
def _recv(self):
    future = None
    while True:
        try:
            if future is None:
                future = asyncio.ensure_future(self._queue.get())
            r = yield from asyncio.wait(
                [future, self._future],
                return_when=asyncio.FIRST_COMPLETED,
                timeout=1.0
            )
            for x in r[0]:
                if x.exception():
                    raise x.exception()
                if x is future:
                    future = None
                print("recv", x.result())
        except BaseException as e:
            print(e)
            break

    print("quit")

used asyncio.ensure_future instead of asyncio.async because later one is deprecated. 使用asyncio.ensure_future而不是asyncio.async因为不推荐使用后者。

It is ok on Python-3.5.1. 在Python 3.5.1上可以。

asyncio.Queue was re-written asyncio.Queue被重写

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM