简体   繁体   English

在 Asyncio 中兼顾生产者和消费者 Python

[英]Juggle Producer and Consumer in Asyncio Python

I have a producer and a consumer async function.我有一个生产者和一个消费者异步 function。 The producer runs first and then three consumers consume the task concurrently.生产者先运行,然后三个消费者同时消费任务。 I want to continue this cadence indefinitely.我想无限期地继续这种节奏。

  • What is the best way to stop the producer and send a signal to the consumer to start running?停止生产者并向消费者发送信号以开始运行的最佳方法是什么?
  • What is the best way to stop the consumer and send a signal to the producer to start running?停止消费者并向生产者发送信号以开始运行的最佳方法是什么?

My current setup looks like this:我当前的设置如下所示:

import asyncio
import time


async def producer(event):
    n = 0
    while True:
        print("Running producer...")
        await asyncio.sleep(0.5)
        n += 1
        if n == 2:
            event.set()
            break


async def consumer(event):
    await event.wait()
    print("Running consumer...")
    await asyncio.sleep(0.5)


async def main():
    event = asyncio.Event()

    tasks = [asyncio.create_task(producer(event))] + [
        asyncio.create_task(consumer(event)) for _ in range(3)
    ]

    await asyncio.gather(*tasks)


while True:
    asyncio.run(main())
    print("\nSleeping for 1 sec...\n")
    time.sleep(1)

This produces the following output:这将产生以下 output:

Running producer...
Running producer...
Running consumer...
Running consumer...
Running consumer...

Sleeping for 1 sec...

Running producer...
Running producer...
Running consumer...
Running consumer...
Running consumer...

The snippet above will run the producer and the two consumers indefinitely.上面的代码片段将无限期地运行生产者和两个消费者。 This works as expected:这按预期工作:

  • The producer and the two consumers run concurrently生产者和两个消费者同时运行
  • The while loop surrounding asyncio.run is running the system indefinitely围绕asyncio.runwhile循环无限期地运行系统

However, I was wondering if there is a better synchronization technique to achieve this long-running periodicity?但是,我想知道是否有更好的同步技术来实现这种长时间运行的周期性?

An alternative to using an event to wake up your consumers is to synchronize the producer and consumers using a queue.使用事件唤醒消费者的另一种方法是使用队列同步生产者和消费者。 The code would look something like代码看起来像

import asyncio


async def producer(queue: asyncio.Queue):
    while True:
        print("Running producer...")
        message = await fetch_message_from_sqs()
        if message:
            await queue.put(message)
        await asyncio.sleep(0.5)


async def consumer(queue: asyncio.Queue):
    while True:
        print("Running consumer...")
        if queue.empty():
            await asyncio.sleep(1)
            continue
        message = await queue.get()
        print(message)
        await acknowledge_message(message)


async def main():
    # You can set a max size if you want to prevent pull too many messages from SQS.
    queue = asyncio.Queue()

    tasks = asyncio.gather(producer(queue), *[consumer(queue) for _ in range(3)])


if __name__ == "__main__":
    asyncio.run(main())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM