Reputation: 656
This code
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))
Produce this output:
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
Why queue become empty, even when I did not yield from
and flow control did not return to loop? I expect, that elements will not "pop" from queue until I will return flow control to loop and it decide to "pop" data.
Upvotes: 1
Views: 642
Reputation: 1733
In the source of 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())
As we can see, if at least one get()
is not fulfilled, any call to put_nowait()
will put an item into the queue, then pop it immediately, giving no chance for the queue to be in a nonempty state.
Upvotes: 3