Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Future в Python — асинхронное выполнение
Future — это объект, который представляет результат асинхронной операции, которая произойдёт в будущем. Это основной строительный блок асинхронного программирования в Python.
Концепция Future
Текущее время Будущее время
↓ ↓
┌────────────────────────────┐
│ Future создан │
│ (результата ещё нет) │
│ ↓ │
│ Операция выполняется │
│ ↓ │
│ Future получает результат │
│ (можно получить значение) │
└────────────────────────────┘
Future в модуле concurrent.futures
ThreadPoolExecutor — многопоточность
from concurrent.futures import ThreadPoolExecutor
import time
def slow_function(n):
time.sleep(2)
return n * 2
# Создание пула потоков
with ThreadPoolExecutor(max_workers=3) as executor:
# Запустить функцию асинхронно
future = executor.submit(slow_function, 5)
print("Код выполняется, пока функция работает в другом потоке")
# Получить результат (блокирует если результата ещё нет)
result = future.result() # Ждёт 2 секунды
print(f"Результат: {result}") # 10
ProcessPoolExecutor — многопроцессность
from concurrent.futures import ProcessPoolExecutor
def cpu_intensive(n):
# Долгая вычислительная операция
total = 0
for i in range(n * 1000000):
total += i
return total
with ProcessPoolExecutor(max_workers=4) as executor:
futures = [executor.submit(cpu_intensive, i) for i in range(1, 5)]
# Получить результаты по мере готовности
for future in futures:
result = future.result()
print(f"Результат: {result}")
Методы Future
result() — получить результат
future = executor.submit(some_function)
value = future.result(timeout=5) # Ждёт максимум 5 сек
done() — проверить готовность
future = executor.submit(slow_function)
if future.done():
print(f"Готово: {future.result()}")
else:
print("Ещё выполняется")
cancel() — отменить выполнение
future = executor.submit(slow_function)
if future.cancel():
print("Успешно отменено")
else:
print("Уже выполняется, отменить нельзя")
add_done_callback() — обработчик завершения
def on_complete(future):
result = future.result()
print(f"Функция завершена! Результат: {result}")
future = executor.submit(slow_function, 5)
future.add_done_callback(on_complete)
# Код продолжает выполняться
as_completed() — обработка результатов по мере готовности
from concurrent.futures import as_completed
urls = ['url1', 'url2', 'url3', 'url4']
with ThreadPoolExecutor(max_workers=4) as executor:
# Запустить задачи
futures = {executor.submit(fetch_url, url): url for url in urls}
# Обработать результаты по мере готовности (не по порядку)
for future in as_completed(futures):
url = futures[future]
try:
data = future.result()
print(f"{url}: успешно получено")
except Exception as e:
print(f"{url}: ошибка {e}")
Future в asyncio
asyncio использует другой подход — async/await (более эффективный для IO):
import asyncio
async def slow_async_function(n):
await asyncio.sleep(2)
return n * 2
async def main():
# Создать Future (в asyncio это Task)
task = asyncio.create_task(slow_async_function(5))
print("Код продолжает выполняться")
# Ждать результат
result = await task
print(f"Результат: {result}") # 10
asyncio.run(main())
Несколько задач параллельно
import asyncio
async def fetch_data(url, delay):
await asyncio.sleep(delay)
return f"Данные с {url}"
async def main():
# Создать несколько задач
tasks = [
asyncio.create_task(fetch_data('url1', 1)),
asyncio.create_task(fetch_data('url2', 2)),
asyncio.create_task(fetch_data('url3', 1.5)),
]
# Ждать все задачи
results = await asyncio.gather(*tasks)
print(results)
# ['Данные с url1', 'Данные с url2', 'Данные с url3']
asyncio.run(main())
Разница: Future vs Task vs async/await
concurrent.futures.Future
# Для многопоточности/многопроцессности
with ThreadPoolExecutor() as e:
future = e.submit(func) # Блокирующая операция
result = future.result() # Ждёт
asyncio.Task
# Для асинхронных операций (IO)
task = asyncio.create_task(async_func()) # Неблокирующая операция
result = await task # Ждёт асинхронно
async/await — рекомендуется
# Более читаемо и эффективно
async def main():
result = await async_func()
Практический пример: загрузка нескольких URL
Плохо (синхронно, медленно)
import requests
urls = ['http://api.example.com/1', 'http://api.example.com/2']
# Займёт ~4 секунды (2 сек + 2 сек)
for url in urls:
response = requests.get(url) # Блокирует
print(response.json())
Хорошо (asyncio, быстро)
import asyncio
import aiohttp
async def fetch(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.json()
async def main():
urls = ['http://api.example.com/1', 'http://api.example.com/2']
# Займёт ~2 секунды (параллельно)
tasks = [asyncio.create_task(fetch(url)) for url in urls]
results = await asyncio.gather(*tasks)
for result in results:
print(result)
asyncio.run(main())
Обработка исключений в Future
from concurrent.futures import ThreadPoolExecutor
def risky_function():
raise ValueError("Что-то пошло не так")
with ThreadPoolExecutor() as executor:
future = executor.submit(risky_function)
try:
result = future.result()
except ValueError as e:
print(f"Перехвачена ошибка: {e}")
Когда использовать Future
concurrent.futures.Future
- CPU-intensive задачи → ProcessPoolExecutor
- Blocking I/O (requests, database) → ThreadPoolExecutor
- Интеграция с legacy кодом
asyncio (рекомендуется)
- Async I/O (aiohttp, asyncpg)
- Много одновременных соединений
- Микросервисы, REST API
- Более эффективен по памяти и CPU
Простое объяснение
Future — это как заказ в кафе:
- Вы заказываете кофе (создаёте Future)
- Кассир принимает заказ и говорит номер
- Вы можете спросить готов ли кофе (future.done())
- Когда кофе готов, вы его получаете (future.result())
Без Future вам пришлось бы ждать у кассы, пока кофе готовится (блокирующее выполнение). С Future вы можете делать другие дела (future.result()), пока кофе готовится в фоне.