在事件循环中共享队列

时间:2018-11-19 13:45:31

标签: python python-asyncio

是否可以在一个事件循环中在不同任务上共享asyncio.Queue?

用例:

两项任务正在将数据发布到队列中,一项任务是从队列中获取新项目。所有任务以异步方式。

main.py

import asyncio
import creator


async def pull_message(queue):
    while True:
        # Here I dont get messages, maybe the queue is always
        # occupied by a other task? 
        msg = await queue.get()
        print(msg)

if __name__ == "__main__"
    loop = asyncio.get_event_loop()
    queue = asyncio.Queue(loop=loop)
    future = asyncio.ensure_future(pull_message(queue))

    creators = list()
    for i in range(2):
        creators.append(loop.create_task(cr.populate_msg(queue)))

    # add future to creators for easy handling
    creators.append(future)
    loop.run_until_complete(asyncio.gather(*creators))

creator.py

import asyncio

async def populate_msg(queue):
    while True:
        msg = "Foo"
        await queue.put(msg)

1 个答案:

答案 0 :(得分:1)

您的代码中的问题是populate_msg不会屈服于事件循环,因为队列是无界的。这有点违反直觉,因为协程显然包含await,但是如果协程否则会阻塞await,则put()仅暂停执行协程。由于无限制队列上的populate_msg永远不会阻塞,因此populate_msg是事件循环执行的唯一操作。

await asyncio.sleep(0)更改为实际执行其他操作(例如等待网络事件)后,问题将消失。出于测试目的,您可以在循环内部添加while,这将迫使协程在array ( [0] => apple, [1] => orange, ) 循环的每次迭代中对事件循环产生控制。请注意,这将导致事件循环通过不断旋转循环来消耗整个内核。