2015-09-16 2 views
1

Этот кодasyncio.queue странное поведение

import asyncio 


@asyncio.coroutine 
def foo(q): 

    print("foo before", q.empty()) 
    q.put_nowait("yoba") 
    print("foo after", q.empty()) 


@asyncio.coroutine 
def bar(q): 

    for _ in range(5): 

     asyncio.async(foo(q)) 
     r = yield from q.get() 
     print("bar received", r) 


q = asyncio.Queue() 
asyncio.get_event_loop().run_until_complete(bar(q)) 

Производят этот вывод:

foo before True 
foo after True 
bar received yoba 
foo before True 
foo after True 
bar received yoba 
foo before True 
foo after True 
bar received yoba 
foo before True 
foo after True 
bar received yoba 
foo before True 
foo after True 
bar received yoba 

Почему очереди становятся пустыми, даже когда я не yield from сделал и контроль не вернулся в цикл потока? Я ожидаю, что элементы не будут «pop» из очереди, пока я не верну управление потоком в цикл, и он решит «поп» данные.

ответ

3

В источнике asyncio.Queue.put_nowait:

if self._getters: 
    assert not self._queue, (
     'queue non-empty, why are getters waiting?') 

    getter = self._getters.popleft() 
    self.__put_internal(item) 

    # getter cannot be cancelled, we just removed done getters 
    getter.set_result(self._get()) 

Как мы можем видеть, если по крайней мере один get() не выполняется, то любой вызов put_nowait() поместит элемент в очереди, а затем вставьте его сразу, не давая шансов, что очередь будет в непустом состоянии.

+0

О, грязный ... в любом случае, спасибо за ответ, я думаю об этом, но не могу поверить, что это правда. Поэтому иногда вы ставите и не пустые, но иногда пустые -_- – broomrider

Смежные вопросы