使用此异步代码,我的导师说,所有协程(此处为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 ...”
答案 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