Что представляет собой объект Future в asyncio?

Ответ

В asyncio, Future — это низкоуровневый объект, который представляет собой результат асинхронной операции, который может быть еще не готов. Он служит для отслеживания состояния выполнения операции (ожидание, завершено, отменено) и получения её конечного результата или возникшего исключения. Концептуально Future схож с Promise в JavaScript или Future в Java.

Назначение: Future позволяет асинхронным функциям «обещать» результат, который будет доступен позже, не блокируя при этом основной поток выполнения. Это критически важно для неблокирующего ввода-вывода и параллельного выполнения задач.

Основные методы:

  • done(): Возвращает True, если Future завершен (успешно, с ошибкой или отменен).
  • result(): Возвращает результат Future. Если Future не завершен, вызывает InvalidStateError. Если завершен с исключением, выбрасывает это исключение.
  • exception(): Возвращает исключение, если Future завершился с ошибкой.
  • set_result(result): Устанавливает результат Future.
  • set_exception(exception): Устанавливает исключение для Future.
  • add_done_callback(callback): Добавляет функцию обратного вызова, которая будет вызвана, когда Future завершится.

Пример использования Future напрямую:

import asyncio

async def set_future_value(future_obj):
    """Имитирует асинхронную операцию, устанавливающую результат Future."""
    print("Начинаем асинхронную операцию...")
    await asyncio.sleep(1) # Имитация задержки
    future_obj.set_result("Данные успешно получены!")
    print("Результат установлен в Future.")

async def main():
    loop = asyncio.get_running_loop() # Получаем текущий цикл событий
    future = loop.create_future() # Создаем объект Future

    # Запускаем корутину, которая установит результат в future
    loop.create_task(set_future_value(future))

    print("Ожидаем результат Future...")
    result = await future # Ожидаем завершения Future
    print(f"Полученный результат: {result}")

if __name__ == "__main__":
    asyncio.run(main())

Важное замечание: В большинстве случаев разработчики не создают Future напрямую. Вместо этого используются высокоуровневые абстракции, такие как asyncio.Task. asyncio.Task — это подкласс Future, который оборачивает корутину и планирует её выполнение в цикле событий. Когда вы используете async def функции и await, вы неявно работаете с Task и Future объектами, которые управляются asyncio.