Photo by an thet / Unsplash

TIL - Python's asyncio.Event Lets Coroutines Signal Each Other Without Polling

Today I Learned May 17, 2026

asyncio.Event is a lightweight one-time signal: coroutines await event.wait() and block until another coroutine calls event.set() - no busy-waiting, no shared booleans guarded by locks.

import asyncio

async def worker(name: str, ready: asyncio.Event):
    print(f"{name}: waiting for start signal")
    await ready.wait()
    print(f"{name}: started work")
    await asyncio.sleep(0.1)
    print(f"{name}: done")

async def main():
    ready = asyncio.Event()
    tasks = [asyncio.create_task(worker(f"W{i}", ready)) for i in range(3)]
    await asyncio.sleep(0.2)   # simulate startup delay
    print("Controller: firing start signal")
    ready.set()                # unblocks ALL waiting coroutines at once

    await asyncio.gather(*tasks)

asyncio.run(main())
# W0, W1, W2 all wait, then all start simultaneously after ready.set()

Event.clear() resets the flag so it can be reused. For more complex signalling where you need to notify one waiter at a time and pass a condition, reach for asyncio.Condition instead.

Tags