简体   繁体   English

Asyncio.Queue 消费者没有被调用

[英]Asyncio.Queue consumer not getting called

I have an asyncio.Queue producer and consumer running as 2 infinite loops.我有一个 asyncio.Queue 生产者和消费者作为 2 个无限循环运行。 The producer periodically adds jobs to the queue and the consumer waits until a job is available, then processes it, then waits for the next job.生产者定期将作业添加到队列中,消费者等待直到有作业可用,然后处理它,然后等待下一个作业。

However, for some reason, my consumer is not getting called.但是,由于某种原因,我的消费者没有被调用。 I think this is because the producer task never yields to the consumer?我认为这是因为生产者任务永远不会屈服于消费者?

Any ideas on how to fix it so that both workers run in the background as described?关于如何修复它的任何想法,以便两个工作人员都按照描述在后台运行?

import asyncio
import concurrent.futures
import time

class Consumer:
    def __init__(self, queue: asyncio.Queue):
        self._duration_before_restart_ms = 3000
        self._queue = queue
        self._last_triggered_time_ms = 0

    async def consumer_loop(self):
        while True:
            print("Consumer new iteration.")
            detected_time_ms = await self._queue.get()
            print("Consumer new event: ", detected_time_ms)
            if (
                detected_time_ms - self._duration_before_restart_ms
                < self._last_triggered_time_ms
            ):
                print("Consumer skipping event: ", detected_time_ms)
                # Invalidate all items in queue that happened before
                # _last_triggered_time_ms.
                continue
            print("Consumer processing event: ", detected_time_ms)
            # Simulate authentication (an io bound operation) with sleep.
            time.sleep(5)
            self._last_triggered_time_ms = int(time.time() * 1000)
            print(
                "Consumer processed event: ",
                detected_time_ms,
                " at: ",
                self._last_triggered_time_ms,
            )


class Producer:
    def __init__(self, queue: asyncio.Queue):
        self._detection_time_period_ms = 3000
        self._last_detection_time_ms = 0
        self._queue = queue

    async def producer_loop(self):
        counter = 0
        while True:
            # Iterates at 2fps
            time.sleep(0.5)
            print("Producer counter: ", counter)
            current_time_ms = int(time.time() * 1000)

            if (counter % 10 > 5) and (
                self._last_detection_time_ms + self._detection_time_period_ms
                < current_time_ms
            ):
                print("Producer adding to queue: ", current_time_ms)
                await self._queue.put(current_time_ms)
                print("Producer added to queue: ", current_time_ms)
                self._last_detection_time_ms = current_time_ms
            counter += 1


async def main():
    q = asyncio.Queue()
    producer = Producer(q)
    consumer = Consumer(q)
    producer_task = asyncio.create_task(producer.producer_loop())
    consumer_task = asyncio.create_task(consumer.consumer_loop())


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

Code works for me if I use await asyncio.sleep() instead of time.sleep()如果我使用await asyncio.sleep()而不是 time.sleep( time.sleep()代码对我有用

In async taks don't run at the same time but it should switch task when it see await - and it seems it needs await asyncio.sleep() to have time to switch from producer to customer, and later to switch back from customer to producer.async任务中不会同时运行,但它应该在看到await时切换任务 - 似乎它需要await asyncio.sleep()有时间从生产者切换到客户,然后再从客户切换回生产者。

You have await in put() and get() but I can't explain why it doesn't switch tasks.您在put()get()中有await但我无法解释为什么它不切换任务。 Maybe it swithc but it switch too fast and it had not enough time to send data in queue.也许它切换了,但切换得太快了,没有足够的时间在队列中发送数据。


import asyncio
import concurrent.futures

class Consumer:

    def __init__(self, queue: asyncio.Queue):
        self._duration_before_restart_ms = 3000
        self._queue = queue
        self._last_triggered_time_ms = 0

    async def consumer_loop(self):
        print('start consumer')

        while True:
            print("Consumer new iteration.")
            detected_time_ms = await self._queue.get()
            print("Consumer new event: ", detected_time_ms)
            if (
                detected_time_ms - self._duration_before_restart_ms
                < self._last_triggered_time_ms
            ):
                print("Consumer skipping event: ", detected_time_ms)
                # Invalidate all items in queue that happened before
                # _last_triggered_time_ms.
                continue
            print("Consumer processing event: ", detected_time_ms)
            # Simulate authentication (an io bound operation) with sleep.
            await asyncio.sleep(5)
            self._last_triggered_time_ms = int(time.time() * 1000)
            print(
                "Consumer processed event: ",
                detected_time_ms,
                " at: ",
                self._last_triggered_time_ms,
            )


class Producer:

    def __init__(self, queue: asyncio.Queue):
        self._detection_time_period_ms = 3000
        self._last_detection_time_ms = 0
        self._queue = queue

    async def producer_loop(self):
        print('start producer')

        counter = 0
        while True:
            # Iterates at 2fps
            await asyncio.sleep(0.5)
            print("Producer counter: ", counter)
            current_time_ms = int(time.time() * 1000)

            if (counter % 10 > 5) and (
                self._last_detection_time_ms + self._detection_time_period_ms
                < current_time_ms
            ):
                print("Producer adding to queue: ", current_time_ms)
                await self._queue.put(current_time_ms)
                print("Producer added to queue: ", current_time_ms)
                self._last_detection_time_ms = current_time_ms
            counter += 1


async def main():
    q = asyncio.Queue()
    producer = Producer(q)
    consumer = Consumer(q)
    producer_task = asyncio.create_task(producer.producer_loop())
    consumer_task = asyncio.create_task(consumer.consumer_loop())

    # wait for end of task
    await asyncio.gather(producer_task)
    
if __name__ == "__main__":
    asyncio.run(main())

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

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