← Назад к вопросам

Зачем нужен future в asyncio?

2.8 Senior🔥 71 комментариев
#Асинхронность и многопоточность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Future в asyncio

Future — это объект в asyncio, который представляет результат асинхронной операции, которая может быть доступна в будущем. Это фундаментальный механизм для работы с асинхронным кодом в Python.

Что такое Future

Future — это объект, который:

  1. Запущен в момент создания
  2. Может быть в состояниях: ожидание, выполнено, ошибка
  3. Может быть ожидаемым (awaited) другими операциями
import asyncio

async def main():
    # Создаём Future
    future = asyncio.Future()
    
    # В будущем устанавливаем результат
    future.set_result("Hello, World!")
    
    # Ожидаем результат
    result = await future
    print(result)  # Output: Hello, World!

asyncio.run(main())

Состояния Future

Future имеет три состояния:

import asyncio
from asyncio import Future

async def example():
    future = asyncio.Future()
    
    # Состояние 1: ожидание (pending)
    print(future.done())  # False (не завершено)
    
    # Состояние 2: выполнено с результатом
    future.set_result(42)
    print(future.done())  # True (завершено)
    print(future.result())  # 42
    
    # Состояние 3: выполнено с ошибкой
    future2 = asyncio.Future()
    future2.set_exception(ValueError("Error!"))
    try:
        await future2
    except ValueError as e:
        print(f"Error: {e}")  # Error: Error!

asyncio.run(example())

Различие между Future и Task

Task — это подкласс Future, который оборачивает корутину:

async def my_coroutine():
    await asyncio.sleep(1)
    return "Done!"

async def main():
    # Future — низкоуровневый объект
    future = asyncio.Future()
    
    # Task — Future, который оборачивает корутину
    task = asyncio.create_task(my_coroutine())
    
    # Оба можно ожидать
    result = await task
    print(result)  # Done!

asyncio.run(main())

Использование Future

1. Связывание результата с функцией (callbacks)

import asyncio

def callback_function(future):
    result = future.result()
    print(f"Future завершён с результатом: {result}")

async def main():
    future = asyncio.Future()
    
    # Добавляем callback
    future.add_done_callback(callback_function)
    
    # Устанавливаем результат (вызовет callback)
    future.set_result("Success!")

asyncio.run(main())

2. Timeout для асинхронных операций

import asyncio

async def long_operation():
    await asyncio.sleep(10)
    return "Done"

async def main():
    try:
        result = await asyncio.wait_for(long_operation(), timeout=2.0)
    except asyncio.TimeoutError:
        print("Операция истекла по timeout")

asyncio.run(main())

3. Ожидание нескольких Future одновременно

import asyncio

async def task1():
    await asyncio.sleep(1)
    return "Task 1"

async def task2():
    await asyncio.sleep(2)
    return "Task 2"

async def main():
    # Создаём tasks
    t1 = asyncio.create_task(task1())
    t2 = asyncio.create_task(task2())
    
    # Ожидаем обе одновременно
    results = await asyncio.gather(t1, t2)
    print(results)  # [Task 1, Task 2]

asyncio.run(main())

4. Ожидание первого завершившегося Future (any)

import asyncio

async def task1():
    await asyncio.sleep(2)
    return "Task 1"

async def task2():
    await asyncio.sleep(1)
    return "Task 2"

async def main():
    t1 = asyncio.create_task(task1())
    t2 = asyncio.create_task(task2())
    
    # Ожидаем первый завершившийся
    done, pending = await asyncio.wait([t1, t2], return_when=asyncio.FIRST_COMPLETED)
    
    for future in done:
        print(f"Завершено: {future.result()}")  # Task 2
    
    # Отменяем оставшиеся
    for future in pending:
        future.cancel()

asyncio.run(main())

Практический пример: веб-скрепер

import asyncio
import aiohttp

async def fetch_url(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = [
        'https://example.com',
        'https://example.org',
        'https://example.net'
    ]
    
    async with aiohttp.ClientSession() as session:
        # Создаём tasks для каждого URL
        tasks = [fetch_url(session, url) for url in urls]
        
        # Ожидаем все одновременно
        results = await asyncio.gather(*tasks)
        
        for url, content in zip(urls, results):
            print(f"{url}: {len(content)} bytes")

asyncio.run(main())

Методы Future

import asyncio

async def example():
    future = asyncio.Future()
    
    # Проверка состояния
    future.done()  # False
    future.cancelled()  # False
    
    # Установка результата
    future.set_result(42)  # Устанавливает результат
    
    # Получение результата
    result = future.result()  # 42
    
    # Обработка исключений
    future2 = asyncio.Future()
    future2.set_exception(ValueError("Error"))
    exception = future2.exception()  # ValueError
    
    # Callbacks
    def done_cb(f):
        print(f"Future завершён: {f.result()}")
    
    future.add_done_callback(done_cb)
    
    # Отмена
    future3 = asyncio.Future()
    future3.cancel()  # Отменяет Future
    print(future3.cancelled())  # True

asyncio.run(example())

Зачем нужны Future

1. Управление асинхронным кодом

  • Отслеживание состояния операции
  • Получение результата когда он будет готов

2. Координация нескольких операций

  • Ожидание всех операций (gather)
  • Ожидание первой (wait с FIRST_COMPLETED)

3. Интеграция с обратными вызовами (callbacks)

  • Код выполняется когда Future завершён
  • Полезно при работе с событийно-ориентированным кодом

4. Работа с timeout

  • Ограничение времени ожидания операции
  • Предотвращение бесконечного зависания

5. Отмена операций

  • Остановка выполнения Future
  • Освобождение ресурсов

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

Зачем нужен future в asyncio? | PrepBro