Зачем нужен future в asyncio?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Future в asyncio
Future — это объект в asyncio, который представляет результат асинхронной операции, которая может быть доступна в будущем. Это фундаментальный механизм для работы с асинхронным кодом в Python.
Что такое Future
Future — это объект, который:
- Запущен в момент создания
- Может быть в состояниях: ожидание, выполнено, ошибка
- Может быть ожидаемым (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, который позволяет писать эффективный и масштабируемый код.