Asyncio

Language: Python

CLI/Utils

Asyncio was introduced in Python 3.4 (2014) to provide a built-in framework for asynchronous programming, inspired by frameworks like Twisted and Tornado. It enables efficient handling of I/O-bound tasks, networking, and high-performance applications without using traditional threading or multiprocessing.

Asyncio is Python's standard library for writing concurrent code using the async/await syntax. It provides an event loop, coroutines, tasks, and futures to facilitate asynchronous programming and I/O-bound operations.

Installation

pip: Included in Python standard library (Python 3.4+)
conda: Included in Python standard library

Usage

Asyncio allows you to define coroutines with `async def`, schedule them for execution, and manage asynchronous tasks. It is ideal for network operations, file I/O, concurrency, and writing scalable applications.

Simple coroutine

import asyncio

async def say_hello():
    print('Hello')
    await asyncio.sleep(1)
    print('World')

asyncio.run(say_hello())

Defines a coroutine using `async def` and runs it with `asyncio.run()`. Demonstrates non-blocking sleep.

Running multiple coroutines concurrently

import asyncio

async def task(name, delay):
    await asyncio.sleep(delay)
    print(f'Task {name} completed')

async def main():
    await asyncio.gather(task('A', 2), task('B', 1))

asyncio.run(main())

Uses `asyncio.gather` to run multiple coroutines concurrently, printing output when each finishes.

Creating tasks

import asyncio

async def my_task():
    await asyncio.sleep(1)
    print('Task done')

task = asyncio.create_task(my_task())
asyncio.run(task)

Wraps a coroutine in a Task, allowing it to run in the background.

Using async context managers

import asyncio

class AsyncResource:
    async def __aenter__(self):
        print('Enter')
        return self
    async def __aexit__(self, exc_type, exc, tb):
        print('Exit')

async def main():
    async with AsyncResource():
        print('Inside context')

asyncio.run(main())

Demonstrates the use of async context managers to manage resources asynchronously.

Networking with asyncio

import asyncio

async def tcp_echo_client(message):
    reader, writer = await asyncio.open_connection('127.0.0.1', 8888)
    writer.write(message.encode())
    await writer.drain()
    data = await reader.read(100)
    print(f'Received: {data.decode()}')
    writer.close()
    await writer.wait_closed()

asyncio.run(tcp_echo_client('Hello'))

Shows a simple TCP client using asyncio for asynchronous network I/O.

Scheduling periodic tasks

import asyncio

async def periodic():
    while True:
        print('Tick')
        await asyncio.sleep(1)

asyncio.run(periodic())

Runs a coroutine repeatedly at fixed intervals using a loop with `await asyncio.sleep()`.

Error Handling

RuntimeError: Event loop is closed: Ensure you are not calling `asyncio.run()` from within an already running event loop.
CancelledError: Occurs when a task is cancelled. Handle with try/except around awaited tasks.
TimeoutError: Use `asyncio.wait_for()` or `asyncio.timeout()` to limit the duration of coroutines safely.

Best Practices

Prefer `asyncio.run()` for top-level entry points in Python 3.7+.

Use `async/await` syntax instead of `@asyncio.coroutine` for readability.

Leverage `asyncio.gather()` for running multiple coroutines concurrently.

Use Tasks for background execution and long-running operations.

Avoid blocking calls in async functions; use non-blocking I/O libraries.