超时后获取完整的aiohttp并行请求

问题描述 投票:2回答:1

我正在使用aiohttp执行一些并行的HTTP发布请求。

我必须全局设置超时(在ClientSession上,以便不超过阈值。

问题是,我想获取在阈值之前我已经完成的(部分会话)响应,因此,例如,如果会话包含10个请求,并且在超时之前我已经完成了5个请求,我想得出这5的结果。但是我还没有弄清楚该怎么做。

我正在使用的代码是这样的:

import aiohttp
import asyncio
import requests

async def fetch(session):
    async with session.get("https://amazon.com") as response:
        return response.status

async def main(n, timeout):
    async with aiohttp.ClientSession(timeout=timeout) as session:
        return await asyncio.gather(*(fetch(session) for _ in range(n)))

timeout = aiohttp.ClientTimeout(total=0.4)
res = asyncio.run(main(10, timeout))
print(res)

使用timeout = 0.4会引发asyncio.TimeoutError,但我不知道如何获得部分执行的响应。

例如,如果我将超时设置为5秒,则所有请求均已完成,并且获得了十个200的列表。

谢谢

python async-await python-asyncio aiohttp
1个回答
1
投票

使用asyncio.wait代替asyncio.gather

completed, pending = await asyncio.wait(
    [fetch(session) for _ in range(n)],
    timeout=timeout
)
for t in pending:  # cancel the pending tasks
    t.cancel()
return [t.result() for t in completed]

注意:wait的timeout参数以秒为单位。

您可能根本不需要为ClientSession指定超时。

请参阅this QA

重新编写的代码(为增加响应时间的差异,我添加了一些不同的来源并执行了20个请求)

import asyncio
import random
import aiohttp
import requests

sources = ["amazon.com", "hotmail.com", "stackoverflow.com"]

async def fetch(session):
    rnd = random.choice(sources)
    async with session.get(f"https://{rnd}") as response:
        return response.status

async def main(n, timeout):
    async with aiohttp.ClientSession() as session:
        completed, pending = await asyncio.wait(
            [fetch(session) for _ in range(n)],
            timeout=timeout
        )
    for t in pending:  # cancel the pending tasks
        t.cancel()
    return [t.result() for t in completed]

timeout = 0.5
res = asyncio.run(main(20, timeout))
print(res)

随着timeout的值增加为0.3、0.5和0.8产生

(.venv) async_req_timeout $ python async_req_timeout.py 
[200, 200]

(.venv) async_req_timeout $ python async_req_timeout.py 
[200, 200, 200, 200, 200, 200, 200, 200, 200, 200]

(.venv) (base) async_req_timeout $ python async_req_timeout.py 
[200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200]
© www.soinside.com 2019 - 2024. All rights reserved.