asyncio код не работает как надо
У меня есть асинхронный код.
import asyncio
from time import time
async def say_yup():
for i in range(10):
await asyncio.sleep(1)
print('yup')
async def gone(n, end_time):
t = time()
while True:
if (time() - t) + n >= end_time:
return
await asyncio.sleep(n)
print(f'{n}s gone')
async def main(n, t):
tasks = [asyncio.create_task(say_yup()), asyncio.create_task(gone(n, t))]
await asyncio.gather(*tasks)
asyncio.run(main(3, 10))
В нём я создал 2 корутины. Я хочу чтобы каждую секунду выводилось сообщение yup и каждые n секунд в течении какого-то времени выводилось:
f'{n}s gone'
В результате, передав в корутину "gone" 3 и 10, я хочу увидеть такой результат выполнения кода:
yup
yup
yup
3s gone
yup
yup
yup
3s gone
yup
yup
yup
3s gone
yup
А получаю такой:
yup
yup
3s gone
yup
yup
yup
3s gone
yup
yup
yup
3s gone
yup
yup
Пожалуйста, помогите исправить код.
Ответы (1 шт):
Когда вы используете sleep нет гарантии сколько точно корутина будет спать. Если две будут спать и проснутся точно в то же время, то какая-то одна из них будет продолжена первой. Если нужно упорядочить их выполнение более строго, то на время и sleep полагаться нельзя.
Т.е у вас требование не просто "каждые три секунды", а "каждые три секунды, но обязательно после того как выполнилось yup". В таком случае нужно делать явную синхронизацию используя механизмы синхронизации, например Event:
async def say_yup(event):
for i in range(10):
await asyncio.sleep(1)
if i % 3 == 2:
event.set()
print('yup')
async def gone(event, n, end_time):
t = time()
while True:
if (time() - t) + n >= end_time:
return
await event.wait()
print(f'{n}s gone')
event.clear()
async def main(n, t):
event = asyncio.Event()
tasks = [asyncio.create_task(say_yup(event)), asyncio.create_task(gone(event, n, t))]
await asyncio.gather(*tasks)