Как подходить к возврату asyn c функции рекурсивно - PullRequest
1 голос
/ 08 января 2020

У меня есть функция, которая рекурсивно пытается извлечь информацию из URL. Если он получает ответ, отличный от 200, он повторяет попытку 3 раза, в итоге возвращая None, если ничего не может быть возвращено. Моя проблема, однако, заключается в том, что когда я запускаю это через событие l oop, вместо того, чтобы снова запускаться как обычная рекурсивная функция, функция просто возвращает сопрограмму, а не ответ JSON или None, как ожидалось.

async def make_request(session, url, attempt=0):
    async with session.get(url) as response:
        if response.status == 200:
            return await response.json()
        elif attempt < 3:
            return await make_request(session, url, attempt + 1) 
            # When it gets to this line, instead of returning the result of this function, 
            # it returns the coroutine object itself.
        return None

Должен ли я запустить что-то заранее, чтобы убедиться, что все работает правильно?

1 Ответ

1 голос
/ 08 января 2020

Невозможно воспроизвести вашу ошибку без полного примера кода. В любом случае, вот код, который работает:

import asyncio
import aiohttp


async def make_request(session, url, attempt=0):
    async with session.get(url) as response:
        if response.status == 200:
            return await response.json()
        elif attempt < 3:
            print(f'failed #{attempt}')  # to debug, remove later
            return await make_request(session, url, attempt + 1)
        return None


async def main():
    async with aiohttp.ClientSession() as session:
        res = await make_request(session, 'http://httpbin.org/status/404')
        print(res)

        res = await make_request(session, 'http://httpbin.org/json')
        print(res)


asyncio.run(main())

Кстати, вместо того, чтобы пытаться писать свои собственные вещи для повторов, вас могут заинтересовать решения других людей, например:

https://github.com/inyutin/aiohttp_retry

https://github.com/hellysmile/async_retrying

...