Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 等待队列。将(项)放到异步IO上。队列似乎不会释放对事件循环的控制_Python_Async Await_Queue_Python Asyncio - Fatal编程技术网

Python 等待队列。将(项)放到异步IO上。队列似乎不会释放对事件循环的控制

Python 等待队列。将(项)放到异步IO上。队列似乎不会释放对事件循环的控制,python,async-await,queue,python-asyncio,Python,Async Await,Queue,Python Asyncio,在这个简单的生产者/消费者示例中,就好像wait queue.put(item)没有释放事件循环以允许消费者运行,直到它完成为止。这会导致生产者将其所有项目放入队列,然后消费者才能将其取下 这是预期的吗 如果我使用await asyncio.sleep(0)跟随wait queue.put(item),我会得到我正在寻找的结果 然后生产者将1个项目放入队列,消费者从队列中取出1个项目 我在Python 3.6.8和3.7.2中得到了相同的结果 import asyncio async def

在这个简单的生产者/消费者示例中,就好像
wait queue.put(item)
没有释放事件循环以允许消费者运行,直到它完成为止。这会导致生产者将其所有项目放入队列,然后消费者才能将其取下

这是预期的吗

如果我使用
await asyncio.sleep(0)
跟随
wait queue.put(item)
,我会得到我正在寻找的结果

然后生产者将1个项目放入队列,消费者从队列中取出1个项目

我在Python 3.6.8和3.7.2中得到了相同的结果

import asyncio

async def produce(queue, n):
    for x in range(1, n + 1):
        print('producing {}/{}'.format(x, n))
        item = str(x)
        await queue.put(item)
        # await asyncio.sleep(0)
    await queue.put(None)

async def consume(queue):
    while True:
        item = await queue.get()
        if item is None:
            break
        print('consuming item {}...'.format(item))

loop = asyncio.get_event_loop()
queue = asyncio.Queue(loop=loop)
producer_coro = produce(queue, 10)
consumer_coro = consume(queue)
loop.run_until_complete(asyncio.gather(producer_coro, consumer_coro))
loop.close()
这会导致生产者将其所有项目放入队列,然后消费者才能将其取下。这是预期的吗

对。问题是,您的队列是无界的,因此将某些内容放入其中不会暂停生产者,因此也不会向其他协同路由屈服。这同样适用于所有立即提供数据的等待,例如a

如果生产者的循环包含另一个暂停源,例如等待实际输入(毕竟它必须从某处获取项目),那么这将导致它暂停,并且问题不会立即被发现。使用
asyncio.sleep(0)
的强制暂停也可以工作,但它很脆弱,因为它依赖于单个暂停来运行使用者。这可能并不总是这样,因为使用者本身可以等待队列以外的一些事件


在某些情况下,无界队列是有意义的,例如当队列中预先充满了任务,或者生产者的体系结构将项目数量限制在合理的数量。但是,如果队列项目是动态生成的,最好添加一个绑定。绑定保证了生产者的反向压力,并确保它不会独占事件循环。

感谢您的明确解释。我原以为wait总是会挂起co例程,并将控制权交还给事件循环,但似乎等待的东西可以立即返回结果,而不是。这是一个适当的泛化还是一个队列。放一个特例?@PaulO是的,这是正确的泛化-
wait
不能保证屈服于事件循环,你可以通过在无限循环中等待一个不可操作的协程来轻松检查。(
asyncio.sleep(0)
实际上是另一个方向。)只有当协程被强制挂起时,事件循环才会接管,因为等待的东西无法提供结果,例如,当等待从尚未准备好读取的套接字读取时,等等。有关更多详细信息,请参阅。