Python异步队列未完成

时间:2018-08-23 21:42:02

标签: python-3.x python-asyncio

我有一个生产者和三个消费者。每个使用者等待获取全局锁后才能继续。程序运行,没有完成,退出while循环。你能告诉我哪里出了问题吗?

import asyncio
import random

async def produce(queue, n):
    for x in range(1, n + 1):
        # produce an item
        print('producing {}/{}'.format(x, n))
        # simulate i/o operation using sleep
        await asyncio.sleep(random.random())
        item = str(x)
        # put the item in the queue
        await queue.put(item)

    # indicate the producer is done
    await queue.put(None)


async def consume(queue, lock):
    while True:
        item = await queue.get()
        if item is None:
            # the producer emits None to indicate that it is done
            break
        # wait for an item from the producer
        async with lock:
            # process the item
            print('consuming item {}...'.format(item))
            # simulate i/o operation using sleep
            await asyncio.sleep(0.3)


loop = asyncio.get_event_loop()
lock = asyncio.Lock()
queue = asyncio.Queue(loop=loop)
producer_coro = produce(queue, 10)
consumers = []
for _ in range(3):
    consumers.append(consume(queue, lock))
all_coroutines = []
all_coroutines.append(producer_coro)
all_coroutines.extend(consumers)
loop.run_until_complete(asyncio.wait(all_coroutines))
loop.close()

2 个答案:

答案 0 :(得分:2)

问题出在消费者身上

        if item is None:
            # the producer emits None to indicate that it is done
            break

None标记仅由单个使用者接收,其余的则等待下一个值通过队列到达。一个简单的解决方法是将前哨值返回到队列:

        if item is None:
            # The producer emits None to indicate that it is done.
            # Propagate it to other consumers and quit.
            await queue.put(None)
            break

或者,produce可以排队与消费者数量一样多的None个哨兵-但这将要求生产者知道有多少消费者,这并不总是可取的。

答案 1 :(得分:0)

添加到@user4815162342 提供的答案中,尝试:

if item is None and queue.qsize() == 0:
    await queue.put(None)
    break

我遇到了一个问题,即消费者还必须queue.put()到同一个队列才能重新运行该函数,但它在没有这两个条件的情况下挂在最后。