异步未在预期的地方停止

时间:2019-03-14 19:35:38

标签: python python-asyncio

使用此异步代码,我的导师说,所有协程(此处为50个“ fetch_page”)首先在第一个async with处停止,然后等待,然后所有它们从那里恢复并在第二个{{1 }},最后它们全部返回。

async with

我正在调试它,我必须说他错了。调试时,我看到所有协程都按顺序进行到第二个import aiohttp import asyncio async def fetch_page(url): print(1) async with aiohttp.ClientSession() as session: print(2) async with session.get(url) as response: print(3) return response.status loop = asyncio.get_event_loop() tasks = [fetch_page('http://google.com') for i in range(50)] loop.run_until_complete(asyncio.gather(*tasks)) ,在那里它们都停止了。然后,一旦所有50个协程恢复,它们就会执行async with并返回。

但是为什么不是所有的协程都停在第一个session.get(url)上?

打印输出:“ 1 2 1 2 1 2 ... 3 3 3 ...”,而不是“ 1 1 1 ... 2 2 2 ... 3 3 3 ...”

2 个答案:

答案 0 :(得分:2)

  

但是为什么不是所有的协程都停在第一个async with上?

await就像其他async with一样,不保证协程会在那里暂停,但是允许在有理由的情况下将协程暂停所以。在这种情况下,仅创建ClientSession是一项无需暂停任何协程就可以完成的操作,因此它们每个都可以继续进行。

输入第二个async with必须获得一个响应对象,该对象要求已发送请求并已接收HTTP标头。在非阻塞套接字上执行,其中一些操作将发出信号,表明该数据不是立即可用的(因为它需要到达服务器,并且服务器必须做出响应,然后响应必须返回给我们) ,并且asyncio通过暂停协程来解决这一问题。这就是为什么实际上保证第二个async with暂停到达它的每个协程的原因。

答案 1 :(得分:1)

这里缺少一些信息:

asyncio是基于事件循环的单线程库。

在这种情况下,发生的情况是aiohttp.ClientSession() as session并不是I / O昂贵的操作,它不需要花费时间来执行,这就是为什么即使在迭代器进入下一个循环之前它也立即被执行。

为什么3333最后打印?因为制作一个I / O需要时间,所以要循环50次以上。

有关更多详细信息,请点击此处:asyncio python doc