Что такое корутины (coroutines)?python-38

Корутины — это специальный тип функций, которые позволяют приостанавливать и возобновлять выполнение, сохраняя при этом состояние между вызовами. Они являются фундаментальной концепцией асинхронного программирования в Python.

Основные характеристики

1. Отличие от обычных функций

  • Приостановка выполнения: могут временно прерываться (через await)
  • Сохранение состояния: запоминают значения переменных между вызовами
  • Кооперативная многозадачность: явно передают управление другим корутинам

2. Ключевые элементы синтаксиса

  • async def: объявление корутины
  • await: точка приостановки выполнения
  • asyncio.run(): запуск корутины
import asyncio

async def simple_coroutine():
    print("Start")
    await asyncio.sleep(1)  # Точка приостановки
    print("End")

Типы корутин

1. Базовые корутины

async def fetch_data():
    return await some_io_operation()

2. Асинхронные генераторы

async def async_counter(n: int):
    for i in range(n):
        await asyncio.sleep(0.1)
        yield i

3. Асинхронные контекстные менеджеры

async def async_context():
    async with some_async_resource() as resource:
        data = await resource.read()

Как работают корутины

1. Механизм выполнения

  1. При вызове корутина возвращает объект-корутину (не начинает выполнение)
  2. Выполняется только при передаче в event loop
  3. В точке await управление возвращается в event loop

2. Пример с цепочкой вызовов

async def process_data():
    raw = await fetch_data()  # Приостановка до завершения fetch_data
    processed = await parse_data(raw)
    return processed

Практическое применение

1. Асинхронные HTTP-запросы

async def fetch_urls(urls):
    tasks = [fetch_single_url(url) for url in urls]
    return await asyncio.gather(*tasks)

2. Работа с WebSockets

async def websocket_handler(websocket):
    async for message in websocket:
        await process_message(message)

3. Параллельные операции ввода-вывода

async def parallel_operations():
    await asyncio.gather(
        write_to_db(),
        send_notification(),
        update_cache()
    )

Внутреннее устройство

1. Реализация через генераторы

Корутины построены на механизме генераторов, но с дополнительной функциональностью:

  • Поддержка await выражений
  • Интеграция с event loop
  • Обработка исключений

2. Отличие от генераторов

  • Генераторы: yield производит значения
  • Корутины: await потребляет значения (обычно другие асинхронные операции)

Ограничения и особенности

  1. Не запускаются напрямую: требуют event loop или другой корутины
  2. Блокирующие вызовы: time.sleep() заблокирует весь event loop
  3. Отладка: сложнее отлаживать из-за асинхронной природы

Резюмируем

Корутины — это мощный инструмент для:

  • Эффективной работы с I/O-bound операциями
  • Создания высокопроизводительных сетевых приложений
  • Реализации сложных асинхронных workflows

Пример с подсветкой (VSCode style):

import asyncio
from typing import AsyncIterator

async def data_stream(limit: int) -> AsyncIterator[int]:
    """Асинхронный генератор данных"""
    for i in range(limit):
        await asyncio.sleep(0.5)  # Имитация I/O операции
        yield i * 2

async def process_stream():
    async for value in data_stream(5):
        print(f"Обработано: {value}")

asyncio.run(process_stream())