Даже при использовании asyncio и aiohttp методы ждут ответа на запрос.

Привет, у меня есть следующая проблема: я хочу выполнить метод getlastItemFromGivenInterval, позволить ему ненадолго пройти, не дожидаясь ответов на запрос, и дать контекст asyncio.sleep(60) для выполнения всей процедуры еще раз за 60-секундные временные рамки. То, что я получаю, ждет в getLastItemFromGivenInterval() завершения запроса.

import aiohttp
import asyncio

loop = asyncio.get_event_loop()
task = loop.create_task(main())
loop.run_forever()

async def main():
    async with aiohttp.ClientSession() as session:
        while True:
            await bc.getLastItemFromGivenInterval(session)
            await asyncio.sleep(60)

async def getLastItemFromGivenInterval(session):
    async with session.get(BinanceClient.base_endpoint + "/api/v1/time") as currentServerTime:
        currentServerTime = await currentServerTime.json()
        currentServerTime = currentServerTime['serverTime']

    async with session.get(url) as res:
        response = await res.json()
        array = []
        print(response)

        return response

getLastItemFromGivenInterval вынесен в отдельный класс. Пожалуйста, дайте мне подсказку, как добиться эффекта ожидания в методе getLastItem...().


person Jack Wilkinson    schedule 30.12.2018    source источник
comment
Я не на 100% понимаю ваш вопрос, но кажется, что ваша проблема в том, что getlastItemFromGivenInterval и sleep синхронны. Если вы хотите запускать их одновременно, то вы, вероятно, хотите дождаться результата asyncio.gather -- await asyncio.gather(bc.getLastItemFromGivenInterval(session), asyncio.sleep(60)), а не чем ждать каждого предмета по отдельности.   -  person mgilson    schedule 30.12.2018
comment
@mgilson Я думаю, что ОП вообще не хочет ждать getLastItemFromGivenInterval. gather() будет распараллеливать сон с выполнением сопрограммы, но это все равно может занять сколь угодно много времени, если сопрограмма в конечном итоге займет много времени, и это то, чего OP пытается избежать.   -  person user4815162342    schedule 31.12.2018
comment
Как получить результат первой сопрограммы в asyncio.gather() сразу после ее завершения?   -  person Jack Wilkinson    schedule 05.01.2019


Ответы (1)


Если я вас правильно понял, вы хотите запустить getLastItemFromGivenInterval в фоновом режиме и делать это каждые 60 секунд, независимо от того, сколько времени потребуется для завершения. Вы можете заменить await на create_task, а затем никогда не ждать результирующей задачи:

loop = asyncio.get_event_loop()
while True:
    # spawn the task in the background, and proceed
    loop.create_task(bc.getLastItemFromGivenInterval(session))
    # wait 60 seconds, allowing the above task (and other
    # tasks managed by the event loop) to run
    await asyncio.sleep(60)

Вы также можете убедиться, что задачи, выполнение которых занимает много времени или которые зависают на неопределенный срок (например, из-за сбоя сети), не накапливаются:

loop = asyncio.get_event_loop()
while True:
    # asyncio.wait_for will cancel the task if it takes longer
    # than the specified duration
    loop.create_task(asyncio.wait_for(
        bc.getLastItemFromGivenInterval(session), 500))
    await asyncio.sleep(60)
person user4815162342    schedule 30.12.2018