asyncio is Python's built-in library for writing concurrent code using the `async`/`await` syntax. It is a framework for writing single-threaded concurrent code using coroutines, multiplexing I/O access over sockets and other resources, running network clients and servers, and other related primitives.
Core Concept: Cooperative Multitasking
Unlike traditional threading where the operating system preemptively switches between threads, asyncio uses cooperative multitasking. This means that a function (a 'coroutine') explicitly yields control back to the 'event loop' when it encounters an operation that would otherwise block (e.g., waiting for network data, reading from a file). While one coroutine is waiting, the event loop can run other ready coroutines, making efficient use of a single thread.
Key Components:
- Coroutines (`async def`): Functions defined with `async def`. They are special functions that can be paused and resumed. When an `async` function is called, it doesn't execute immediately; instead, it returns a coroutine object that can be `await`ed.
- `await`: Used inside an `async` function to pause its execution until the 'awaitable' (another coroutine, a Task, or a Future) completes. While paused, the event loop can execute other tasks.
- Event Loop: The heart of asyncio. It manages and distributes events, runs tasks, and handles I/O operations. It keeps track of which coroutines are ready to run and which are waiting for something.
- Tasks (`asyncio.create_task`): Wraps a coroutine and schedules it to be run by the event loop. Tasks are a subclass of `Future` and represent an independent unit of execution.
- `asyncio.run()`: The high-level entry point to run the event loop and execute the main coroutine. It handles the setup and shutdown of the event loop.
Advantages:
- High Concurrency with Low Overhead: Achieves concurrency without the overhead of multiple OS threads/processes, making it efficient for I/O-bound workloads.
- Non-Blocking I/O: Ideal for applications that spend most of their time waiting for external resources (network requests, database queries, file I/O).
- Improved Responsiveness: Keeps the application responsive by not blocking the entire program during slow operations.
- Scalability: Can handle many concurrent connections or operations efficiently on a single thread.
Use Cases:
- Building high-performance web servers and API clients.
- Developing network applications (proxies, chat servers).
- Asynchronous database access.
- Data streaming and processing.
- Any I/O-bound application where responsiveness and scalability are critical.
Example Code
import asyncio
import time
async def say_hello(name, delay):
print(f"[{time.strftime('%H:%M:%S')}] {name}: Starting...")
await asyncio.sleep(delay) Simulate an I/O-bound operation
print(f"[{time.strftime('%H:%M:%S')}] {name}: Finished after {delay} seconds.")
return f"Hello, {name}!"
async def main():
print(f"[{time.strftime('%H:%M:%S')}] Main: Starting main coroutine.")
Create tasks for concurrent execution
task1 = asyncio.create_task(say_hello("Alice", 2))
task2 = asyncio.create_task(say_hello("Bob", 1))
task3 = asyncio.create_task(say_hello("Charlie", 3))
Await the completion of all tasks
asyncio.gather runs awaitables concurrently and waits for them to complete.
results = await asyncio.gather(task1, task2, task3)
print(f"[{time.strftime('%H:%M:%S')}] Main: All tasks completed.")
for res in results:
print(f"[{time.strftime('%H:%M:%S')}] Result: {res}")
if __name__ == "__main__":
asyncio.run() is the high-level entry point for running asyncio programs.
It handles creating a new event loop, running the main coroutine, and closing the loop.
asyncio.run(main())
print(f"[{time.strftime('%H:%M:%S')}] Program finished.")








asyncio