简体   繁体   English

如何使用 python asyncio 对 consumer.producer 进行编码?

[英]How to code consumer.producer with python asyncio?

My Python version is 3.6.1.我的 Python 版本是 3.6.1。

I wrote something to implement a model of consumer-producer with Python asyncio.我写了一些东西来使用 Python asyncio 来实现消费者生产者的 model。 But it doesn't work as expected.但它没有按预期工作。

Four events all created but none of any print export.四个事件全部创建,但没有任何打印导出。

async def consumer(queue, id):
    while True:
        val = await queue.get()
        print('{} get a val: {}'.format(id, val))
        await asyncio.sleep(1)

async def producer(queue, id):
    for i in range(5):
        val = random.randint(1, 10)
        await queue.put(val)
        print('{} put a val: {}'.format(id, val))
        await asyncio.sleep(1)

async def main():
    queue = asyncio.Queue()

    consumer_1 = asyncio.ensure_future(consumer(queue, 'consumer_1'))
    consumer_2 = asyncio.ensure_future(consumer(queue, 'consumer_2'))

    producer_1 = asyncio.ensure_future(producer(queue, 'producer_1'))
    producer_2 = asyncio.ensure_future(producer(queue, 'producer_2'))

    await asyncio.sleep(10)
    consumer_1.cancel()
    consumer_2.cancel()

    await asyncio.gather(consumer_1, consumer_2, producer_1, producer_2, return_exceptions=True)

loop = asyncio.get_event_loop()
tasks = [asyncio.ensure_future(main())]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

Could U please help me correct?你能帮我改正吗?

A lot of wrong things in your approach, some of those are: 您的方法中有很多错误的地方,其中包括:

  • unnecessary asyncio.ensure_future for producers 生产者不必要的asyncio.ensure_future
  • asyncio.gather ing in arbitrary order with doubtful items 以可疑项目以任意顺序asyncio.gather
  • unnecessary tasks = [asyncio.ensure_future(main())] and asyncio.wait(tasks) actions 不必要的tasks = [asyncio.ensure_future(main())]asyncio.wait(tasks)操作
  • uncontrolled queue 不受控制的queue

Example of asyncio Producer/consumer scheme: https://asyncio.readthedocs.io/en/latest/producer_consumer.html 异步生产者/消费者方案的示例: https ://asyncio.readthedocs.io/en/latest/producer_consumer.html


The correct producer/consumer scheme would look as below (for your case): 正确的生产者/消费者方案如下所示(针对您的情况):

import asyncio
import random

async def consumer(queue, id):
    while True:
        val = await queue.get()
        print('{} get a val: {}'.format(id, val))
        await asyncio.sleep(1)
        queue.task_done()   # indicate complete task

async def producer(queue, id):
    for i in range(5):
        val = random.randint(1, 10)
        await asyncio.sleep(1)
        await queue.put(val)
        print('{} put a val: {}'.format(id, val))


async def main():
    queue = asyncio.Queue()

    producer_1 = producer(queue, 'producer_1')
    producer_2 = producer(queue, 'producer_2')

    consumer_1 = asyncio.ensure_future(consumer(queue, 'consumer_1'))
    consumer_2 = asyncio.ensure_future(consumer(queue, 'consumer_2'))

    await asyncio.gather(*[producer_1, producer_2], return_exceptions=True)
    await queue.join()  # wait until the consumer has processed all items
    consumer_1.cancel()
    consumer_2.cancel()

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close() 

The output: 输出:

producer_1 put a val: 7
producer_2 put a val: 2
consumer_1 get a val: 7
consumer_2 get a val: 2
producer_1 put a val: 9
producer_2 put a val: 2
consumer_1 get a val: 9
consumer_2 get a val: 2
producer_1 put a val: 9
producer_2 put a val: 3
consumer_1 get a val: 9
consumer_2 get a val: 3
producer_1 put a val: 1
producer_2 put a val: 6
consumer_1 get a val: 1
consumer_2 get a val: 6
producer_1 put a val: 2
producer_2 put a val: 2
consumer_1 get a val: 2
consumer_2 get a val: 2

I came up with this layout as it is very clean, simple and easy to understand the asyncio code:我想出了这个布局,因为它非常干净、简单且易于理解 asyncio 代码:

import asyncio


async def producer(queue):
    i = 1
    while True:
        await queue.put(f'item {i}')
        i += 1
        await asyncio.sleep(5)


async def consumer(queue):
    while True:
        item = await queue.get()
        print(item)


if __name__ == '__main__':
    queue = asyncio.Queue()

    loop = asyncio.get_event_loop()
    loop.create_task(producer(queue))
    loop.create_task(consumer(queue))
    loop.run_forever()

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

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