简体   繁体   English

使用 asyncio.gather 时正确捕获 aiohttp TimeoutError

[英]Correctly catch aiohttp TimeoutError when using asyncio.gather

It is my first question here on Stack Overflow so I apologize if I did something stupid or missed something.这是我在 Stack Overflow 上的第一个问题,所以如果我做了一些愚蠢的事情或错过了什么,我深表歉意。

I am trying to make asynchronous aiohttp GET requests to many api endpoints at a time to check the status of these pages: the result should be a triple of the form ( url , True , "200" ) in case of a working link and ( url , False , response_status ) in case of a "problematic link".我正在尝试一次向许多 api 端点发出异步 aiohttp GET 请求以检查这些页面的状态:结果应该是形式的三元组( urlTrue"200" )在工作链接的情况下和( urlFalseresponse_status )在“有问题的链接”的情况下。 This is the atomic function for each call:这是每次调用的原子 function:

async def ping_url(url, session, headers, endpoint):

    try:
        async with session.get((url + endpoint), timeout=5, headers=headers) as response:
            return url, (response.status == 200), str(response.status)
    except Exception as e:
        test_logger.info(url + ": " + e.__class__.__name__)
        return url, False, repr(e)

These are wrapped into a function using asyncio.gather() which also creates the aiohttp Session:这些使用 asyncio.gather() 包装到 function 中,它还创建了 aiohttp Session:

async def ping_urls(urllist, endpoint):

   headers = ... # not relevant

   async with ClientSession() as session:
        try:
            results = await asyncio.gather(*[ping_url(url, session, headers, endpoint) \
                      for url in urllist],return_exceptions=True)
        except Exception as e:
            print(repr(e))
   return results

The whole called from a main that looks like this:从一个看起来像这样的主调用的整体:

    urls = ... # not relevant
    loop = asyncio.get_event_loop()
    try:
        loop.run_until_complete(ping_urls(urls, endpoint))

    except Exception as e:
        pass
    finally:
        loop.close()

This works most of the time, but if the list is pretty long, I noticed that as soon as I get one这在大多数情况下都有效,但如果列表很长,我一拿到就注意到了

TimeoutError

the execution loop stops and I get TimeoutError for all other urls after the first one that timed out.执行循环停止,在第一个超时之后我得到所有其他 url 的 TimeoutError。 If I omit the timeout in the innermost function I get somehow better results, but then it is not that fast anymore.如果我省略最里面的超时 function 我会得到更好的结果,但它不再那么快了。 Is there a way to control the Timeouts for the single api calls instead of a big general timeout for the whole list of urls?有没有办法控制单个 api 调用的超时,而不是控制整个 url 列表的一般超时?

Any kind of help would be extremely appreciated, I got stuck with my bachelor thesis because of this issue.任何形式的帮助都将不胜感激,由于这个问题,我的学士论文陷入困境。

You may want to try setting a session timeout for your client session.您可能想尝试为您的客户端会话设置会话超时。 This can be done like:这可以像这样完成:

async def ping_urls(urllist, endpoint):
    headers = ... # not relevant

    timeout = ClientTimeout(total=TIMEOUT_SECONDS)
    async with ClientSession(timeout=timeout) as session:
        try:
            results = await asyncio.gather(
               *[
                    ping_url(url, session, headers, endpoint)
                    for url in urllist
                ],
                return_exceptions=True
            )
        except Exception as e:
            print(repr(e))

        return results

This should set the ClientSession instance to have TIMEOUT_SECONDS as the timeout.这应该将 ClientSession 实例设置为TIMEOUT_SECONDS作为超时。 Obviously you will need to set that value to something appropriate!显然,您需要将该值设置为适当的值!

I struggled with the exceptions as well.我也为例外而苦苦挣扎。 I then found the hint, that I can also show the type of the Exception.然后我发现提示,我还可以显示异常的类型。 And with that create appropriate Exception handling.并以此创建适当的异常处理。

try: ...
except Exception as e:
     print(f'Error: {e} of Type: {type(e)}')

So, with this you can find out, what kind of errors occur and you can catch and handle them individually.所以,有了这个,你可以找出发生了什么类型的错误,你可以单独捕获和处理它们。

eg例如

try: ...
except aiohttp.ClientConnectionError as e:
    # deal with this type of exception
except aiohttp.ClientResponseError as e:
    # handle individually
except asyncio.exceptions.TimeoutError as e:
    # these kind of errors happened to me as well

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM