Мне нужно периодически вызывать задачу, но (а) время ожидания почти больше, чем период.
В следующем коде Как я могу запустить задачу do_something()
без необходимости await
для результата?
import asyncio
import time
from random import randint
period = 1 # Second
def get_epoch_ms():
return int(time.time() * 1000.0)
async def do_something(name):
print("Start :", name, get_epoch_ms())
try:
# Do something which may takes more than 1 secs.
slp = randint(1, 5)
print("Sleep :", name, get_epoch_ms(), slp)
await asyncio.sleep(slp)
except Exception as e:
print("Error :", e)
print("Finish :", name, get_epoch_ms())
async def main():
i = 0
while True:
i += 1
# Todo : this line should be change
await do_something('T' + str(i))
await asyncio.sleep(period)
asyncio.get_event_loop().run_until_complete(main())
Да, конечно. Я использую вызовы API для получения данных о криптовалюте с нескольких веб-сайтов. Моя цель - вызвать API получения данных с постоянным периодом (среднее значение последних периодов). давайте предположим, что 60 запросов в минуту. некоторые сайты ленятся отвечать. например, предположим, что все ответы будут доставлены через 10 секунд. на самом деле мне все равно, когда будет получен ответ (или даже у него может быть ошибка тайм-аута через 60 секунд). это ожидание ответа API раздражает. Я просто хочу отправлять запросы с одинаковыми периодами.
Вместо того, чтобы запускать сопрограмму, вызовите await
, чтобы создать объект задачи, который работает в фоновом режиме. На следующей итерации вы можете проверить, выполнена ли задача, и соответственно ожидать/отменить ее. (В противном случае asyncio будет жаловаться на то, что неожиданные задачи удаляются сборщиком мусора.)
Ваша проблема заключается в использовании run_until_complete(main())
, который не удовлетворяет вашей цели параллелизма. Итак, если предположить, что ваши задачи сопрограммы (do_something()
) ограничены 5
, ваш код будет следующим:
import time
from random import randint
period = 1 # Second
def get_epoch_ms():
return int(time.time() * 1000.0)
async def do_something(name):
print("Start :", name, get_epoch_ms())
try:
# Do something which may takes more than 1 secs.
slp = randint(1, 5)
print("Sleep :", name, get_epoch_ms(), slp)
await asyncio.sleep(slp)
except Exception as e:
print("Error :", e)
print("Finish :", name, get_epoch_ms())
loop = asyncio.get_event_loop()
futures = [loop.create_task(do_something('T' + str(i)))
for i in range(5)]
loop.run_forever()
for f in futures:
f.cancel()
Вот рабочий процесс параллелизма в его выводе:
Start : T0 1558937750705
Sleep : T0 1558937750705 5
Start : T1 1558937750705
Sleep : T1 1558937750705 1
Start : T2 1558937750705
Sleep : T2 1558937750705 4
Start : T3 1558937750705
Sleep : T3 1558937750705 5
Start : T4 1558937750705
Sleep : T4 1558937750705 5
Finish : T1 1558937751707
Finish : T2 1558937754709
Finish : T0 1558937755707
Finish : T3 1558937755708
Finish : T4 1558937755708
Однако, если ваши задачи сопрограммы не ограничены, вы можете это сделать:
...
async def main(loop):
i = 0
while True:
i += 1
loop.create_task(do_something('T' + str(i)))
await asyncio.sleep(period)
loop = asyncio.get_event_loop()
loop.run_until_complete(main(loop))
Время ожидания результата не может быть меньше, чем время, необходимое для его получения. Можете подробнее описать проблему?