Answer the question
In order to leave comments, you need to log in
Is the order of asyncio.Event.set() calls guaranteed to match the wakeup order of the coroutines hanging on them?
Подробнее:
Есть n asyncio.Event, на каждом из них висит ровно одна корутина (await asyncio.Event.wait()).
Метод asyncio.Event.set() - не корутина, и его вызов сразу же не отдает управление разбуженной корутине.
Вопрос: если я в цикле вызову на всех ивентах set(), то разбуженные корутины гарантированно начнут работу в том же порядке, в каком я вызвал set() на соответсвтующем ивенте?
Вот пример:
import asyncio
async def coro(n, event):
await event.wait()
print(n)
async def main():
events = []
for i in range(10):
event = asyncio.Event()
events.append(event)
asyncio.create_task(coro(i, event))
await asyncio.sleep(2)
for ev in events[5:] + events[:5]: # (1)
ev.set()
print('all events are set')
await asyncio.sleep(2) # да, я знаю, что не так нужно дожидаться завершения корутин
if __name__ == '__main__':
asyncio.run(main())
Answer the question
In order to leave comments, you need to log in
А как порядок может быть другим? У вас же кооперативная многозадачность.
1) Вы в цикле насоздавали тасков, каждый из которых - это легковесный тред под управлением планировщика asyncio, каждый из них при запуске отдаёт управление обратно планировщику, добавляясь в список на оповещение по event.
2) Потом вы отдали управление планировщику на 2 секунды (зачем?)
3) Вы в фиксированном порядке вызываете ev.set(), что приводит к точно такому-же фиксированному порядку оповещения подписчиков.
Вообще такие штуки надо смотреть в коде, только там можно узнать правду :)
def set(self):
"""Set the internal flag to true. All coroutines waiting for it to
become true are awakened. Coroutine that call wait() once the flag is
true will not block at all.
"""
if not self._value:
self._value = True
for fut in self._waiters:
if not fut.done():
fut.set_result(True)
@coroutine
def wait(self):
"""Block until the internal flag is true.
If the internal flag is true on entry, return True
immediately. Otherwise, block until another coroutine calls
set() to set the flag to true, then return True.
"""
if self._value:
return True
fut = self._loop.create_future()
self._waiters.append(fut)
try:
yield from fut
return True
finally:
self._waiters.remove(fut)
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question