簡體   English   中英

await queue.put(item)到asyncio.Queue似乎沒有釋放對事件循環的控制

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM