[英]await queue.put(item) onto a asyncio.Queue does not seem to release control of the event loop
在這個簡單的生產者/消費者示例中,好像await queue.put(item)
不會釋放事件循環以允許使用者運行直到完成。 這導致生產者將所有項目放入隊列,然后消費者才能將其取消。
這是預期的嗎?
如果我使用await asyncio.sleep(0)
跟隨await queue.put(item)
,我會得到我正在尋找的結果。
然后,生產者將1個項目放入隊列,然后消費者從隊列中取出1個項目。
我在Python 3.6.8和3.7.2中得到了相同的結果。
import asyncio
async def produce(queue, n):
for x in range(1, n + 1):
print('producing {}/{}'.format(x, n))
item = str(x)
await queue.put(item)
# await asyncio.sleep(0)
await queue.put(None)
async def consume(queue):
while True:
item = await queue.get()
if item is None:
break
print('consuming item {}...'.format(item))
loop = asyncio.get_event_loop()
queue = asyncio.Queue(loop=loop)
producer_coro = produce(queue, 10)
consumer_coro = consume(queue)
loop.run_until_complete(asyncio.gather(producer_coro, consumer_coro))
loop.close()
這導致生產者將所有項目放入隊列,然后消費者才能將其取消。 這是預期的嗎?
是。 問題是你的隊列是無限制的,所以把東西放到它里面永遠不會暫停生產者,因此永遠不會產生其他協同程序。 對於立即提供數據的所有等待都是如此,例如在EOF讀取 。
如果生產者的循環包含另一個暫停源,例如等待實際輸入(它必須從某個地方獲取項目,畢竟),那么這將導致它暫停並且問題不會立即引起注意。 使用asyncio.sleep(0)
強制暫停也可以,但它很脆弱,因為它依賴於一個暫停來運行消費者。 這可能並非總是如此,因為消費者本身可以等待除隊列之外的一些事件。
在某些情況下,無限制隊列是有意義的,例如當隊列預先填充任務時,或者生產者的體系結構將項目數限制為合理的數量。 但是如果隊列項是動態生成的,最好添加一個綁定。 綁定保證了生產者的后抑制,並確保它不會獨占事件循環。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.