为什么asyncio.queue得到faild?

时间:2016-01-07 07:28:08

标签: python python-3.x queue python-asyncio

Python3,asyncio 任务A每隔2秒将一个数字放入一个队列, 任务B在永久循环中等待queue.get(),超时1秒。

我不知道为什么无法从任务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()

输出:

wait
wait
feed
wait
wait
feed
wait
wait
feed
wait

2 个答案:

答案 0 :(得分:0)

self._queue.get()的第一次调用可能会返回该值,但未使用该值,并且会进行新的调用。

调整为使用通话(并使用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")

使用了asyncio.ensure_future而不是asyncio.async,因为后面的版本已被弃用。

答案 1 :(得分:0)

在Python-3.5.1上没问题。

asyncio.Queue被重写