我有一个 python 脚本,它异步发出 http 请求,提供了一个 url 列表,下面是示例代码。
#!/usr/local/bin/python3
import httpx
import asyncio
async def httpx_get(client, url):
resp1 = await client.get(url, timeout=5, allow_redirects=True)
# ... other computation ...
resp2 = await client.get(url, timeout=5, allow_redirects=True) # what happens during this second await?
async def fetch_pages(urls):
async with httpx.AsyncClient(verify=False) as client:
# create task for all URLs
coros = []
for url in urls:
coros.append(asyncio.create_task(httpx_get(client, url)))
# await all tasks
for coro in asyncio.as_completed(coros):
resp = await coro
def main():
urls = [ "https://google.com", "https://yahoo.com", "https://youtube.com" ]
asyncio.run(fetch_pages(urls))
if __name__ == "__main__":
main()
我意识到我对 asyncio 何时处理我的 httpx_get
中的第二个等待 resp2 = wait client.get(..
) 缺乏了解功能。
由于 for coro in asyncio.as_completed(coros): resp = wait coro
仅解析每个协程的第一个等待,resp1 = wait client.get
,当第二个await resp2 = wait client.get
得到解决吗?
第二个等待/请求是否立即执行并等待所有?还是发生了其他事情?如有任何澄清,我们将不胜感激,谢谢!
最佳答案
...when asyncio would handle the second await, resp2 = await client.get(.., in my httpx_get function.
在第一次等待时,事件循环将暂停此任务并继续执行其他操作,最终检查 client.get
是否已返回。如果有此任务,它将继续执行,直到遇到第二个等待 resp2 =await...
事件循环会像第一个一样处理第二个 await
- 它会挂起任务并继续继续做其他事情,直到它检查协程是否已返回。
这是一个用时间延迟来代替检索 URL 的示例 - 希望它是类似的,并且将显示您的流程可能会如何演变。
import asyncio,random,time
async def httpx_get(client, url):
print(f'{time.time()} task:{client} resp1 will be called')
resp1 = await asyncio.sleep(random.randrange(1,10))
# ... other computation ...
print(f'{time.time()} task:{client} resp1 returned')
print(f'{time.time()} task:{client} executing')
print(f'{time.time()} task:{client} executing')
print(f'{time.time()} task:{client} executing')
print(f'{time.time()} task:{client} executing')
print(f'{time.time()} task:{client} resp2 will be called')
resp2 = await asyncio.sleep(random.randrange(1,10))
print(f'{time.time()} task:{client} resp2 returned')
return f'{time.time()} task:{client} finished - url'
async def fetch_pages(urls):
# create task for all URLs
coros = []
for n,url in enumerate(urls):
coros.append(asyncio.create_task(httpx_get(n, url)))
# await all tasks
for coro in asyncio.as_completed(coros):
resp = await coro
print(f'{time.time()} {resp}')
def main():
urls = [ "https://google.com", "https://yahoo.com", "https://youtube.com" ]
asyncio.run(fetch_pages(urls))
if __name__ == "__main__":
main()
执行结果:
1659744155.1480112 task:0 resp1 will be called and awaited
1659744155.1480112 task:1 resp1 will be called and awaited
1659744155.1480112 task:2 resp1 will be called and awaited
1659744161.152556 task:2 resp1 returned
1659744161.152556 task:2 executing
1659744161.152556 task:2 executing
1659744161.152556 task:2 executing
1659744161.154198 task:2 executing
1659744161.154198 task:2 resp2 will be called and awaited
1659744163.1660972 task:1 resp1 returned
1659744163.1660972 task:1 executing
1659744163.1660972 task:1 executing
1659744163.1660972 task:1 executing
1659744163.1660972 task:1 executing
1659744163.1675234 task:1 resp2 will be called and awaited
1659744164.1542242 task:0 resp1 returned
1659744164.1542242 task:0 executing
1659744164.1542242 task:0 executing
1659744164.1542242 task:0 executing
1659744164.155838 task:0 executing
1659744164.155838 task:0 resp2 will be called and awaited
1659744166.167943 task:2 resp2 returned
1659744166.167943 1659744166.167943 task:2 finished - https://youtube.com
1659744168.1679864 task:1 resp2 returned
1659744168.1685212 1659744168.1685212 task:1 finished - https://yahoo.com
1659744169.1565957 task:0 resp2 returned
1659744169.1565957 1659744169.1565957 task:0 finished - https://google.com
关于python - AsyncIO 这个任务什么时候发生第二次await?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73229524/