Ответ
В 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.
Ответ 18+ 🔞
Слушай, а вот этот твой asyncio.Future — это такая штука, которая обещает тебе результат, но ещё нихуя не сделала. Представь, ты заказал пиццу, а тебе дали пустую коробку и сказали: «Жди, мужик, сейчас наполним». Вот эта коробка — и есть Future. Она пока пустая, но в ней может появиться либо пицца, либо, если курьер упал, — хуй с солью.
Зачем это надо, блядь? Чтобы не стоять как идиот и не пялиться в потолок, пока операция выполняется. Ты говоришь: «Окей, Future, как будешь готов — пискни». А сам в это время можешь другие дела делать, ебашить параллельно. Это основа всего асинхронного движняка — никаких блокировок, всё летает.
Что с ним можно делать, этот Future:
done()— глянуть, готово ли уже, или всё ещё в процессе. True — значит, пицца в коробке (или таракан, если не повезло).result()— открыть коробку и достать что внутри. Если открыть раньше времени — получишь ошибку в еблет. Если внутри исключение — оно тебе в рожу выскочит.exception()— специально посмотреть, не засунули ли тебе в коробку исключение вместо пиццы.set_result()— вот этим методом ты сам кладёшь пиццу в коробку. Типа, «всё, готово, на, жри».set_exception()— а этим — подкладываешь кирпич. «Извини, братан, не срослось».add_done_callback()— повесить колбэк, который сработает, когда коробка наполнится. Типа «позвони мне, когда придёт».
Вот тебе живой пример, смотри:
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() # Создаём пустую коробку-обещание
# Запускаем задачу, которая эту коробку наполнит
loop.create_task(set_future_value(future))
print("Сижу, жду, когда Future созреет...")
result = await future # Тут мы реально ждём, пока коробку наполнят
print(f"Получил: {result}")
if __name__ == "__main__":
asyncio.run(main())
Но есть важный момент, ёпта!
В нормальной жизни ты редко когда будешь вручную эти Future создавать и пихать в них результаты. Это как собирать двигатель из говна и палок — можно, но зачем, если есть завод? Высокоуровневая абстракция — asyncio.Task. Это тот же Future, но он уже обёрнут вокруг твоей корутины (async def функции) и сам всем управляет. Когда ты пишешь await some_coro(), под капотом как раз создаётся Task (наследник Future), который и крутится в цикле событий. Так что не выёбывайся с низкоуровневыми фьючами без крайней нужды.