问题
My Python version is 3.6.1.
I wrote something to implement a model of consumer-producer with Python asyncio. 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?
回答1:
A lot of wrong things in your approach, some of those are:
- unnecessary
asyncio.ensure_future
for producers asyncio.gather
ing in arbitrary order with doubtful items- unnecessary
tasks = [asyncio.ensure_future(main())]
andasyncio.wait(tasks)
actions - uncontrolled
queue
Example of asyncio Producer/consumer scheme: 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
来源:https://stackoverflow.com/questions/57026255/how-to-code-consumer-producer-with-python-asyncio