How to Signal asyncio Workers to Stop with an Event in Python
Use an asyncio.Event to coordinate graceful shutdown of multiple concurrent worker tasks in Python.
Python code
22 linesimport asyncio
import random
async def worker(name, stop_event):
while not stop_event.is_set():
await asyncio.sleep(random.uniform(0.1, 0.5))
print(f"Worker {name} processing...")
print(f"Worker {name} stopped.")
async def main():
stop_event = asyncio.Event()
workers = [asyncio.create_task(worker(i, stop_event)) for i in range(3)]
await asyncio.sleep(1.2)
print("Signaling workers to stop...")
stop_event.set()
await asyncio.gather(*workers)
print("All workers stopped.")
if __name__ == "__main__":
asyncio.run(main())
Output
Worker 0 processing...
Worker 2 processing...
Worker 1 processing...
Worker 2 processing...
Worker 0 processing...
Worker 1 processing...
Signaling workers to stop...
Worker 2 stopped.
Worker 1 stopped.
Worker 0 stopped.
All workers stopped.
How it works
The asyncio.Event acts as a simple flag that multiple coroutines can monitor. Each worker loop checks stop_event.is_set() in its while condition; when the event is set from main, all active iterations end. asyncio.gather waits for every worker task to finish, ensuring a clean shutdown. The await asyncio.sleep inside the loop yields control to the event loop, allowing all workers to run concurrently.
Common mistakes
- Calling `stop_event.set()` before workers start checking it, causing them to never run.
- Forgetting to `await asyncio.gather`, leaving tasks incomplete on program exit.
- Using `time.sleep` instead of `asyncio.sleep`, blocking the event loop.
Variations
- Pass a `asyncio.CancelledError` handler to gracefully catch task cancellation instead of using an event.
- Use `stop_event.wait()` inside the loop for a blocking-style check that yields control.
Real-world use cases
- Gracefully stopping background data-collection workers when a shutdown signal is received in a server.
- Coordinating multiple producer or consumer tasks to halt when a job is aborted or a timeout occurs.
- Signaling a pool of monitoring coroutines to exit when a system is taken offline for maintenance.
Sponsored
More from Concurrency & performance
- Benchmark list.append vs deque.append in Python medium
- Build a Python Performance Profiler That Generates Readable Reports medium
- Graceful Shutdown Executor Context Manager in Python medium
- How to Build a Producer-Consumer Pattern with asyncio.Queue in Python medium
- How to Cancel an asyncio Task with Graceful Cleanup in Python medium
- How to Convert Data in Parallel with ThreadPoolExecutor in Python easy
Keep learning
Related tutorials and quizzes for this topic.