python - AsyncIO 这个任务什么时候发生第二次await?

标签 python python-3.x asynchronous async-await python-asyncio

我有一个 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/

相关文章:

python-3.x - 使用 python 求解 x

c# - HttpClient.PostAsync 花费的时间是实际延迟的两倍?

python - 删除python3中html标签之间的换行符

python - 在 django 中获取多个站点 id 的问题

python - Airflow PythonVirtualenvOperator,没有那个文件或目录 : 'virtualenv'

python - 只允许 pyqt4 应用程序的一个实例

python - 为什么只打印横幅,并在结果上挂起/超时? --Python3(套接字,sys)

asynchronous - 如何在 Tokio future 链的多个分支中使用 TcpStream?

c# - 使用 Async CTP 在单个函数中异步 HTTP 发布数据

python - 折叠/展开文本小部件中的文本