← Назад к вопросам
Какие знаешь Awaitable объекты в asyncio?
2.8 Senior🔥 151 комментариев
#Python Core#Асинхронность и многопоточность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Awaitable объекты в asyncio
Awaitable — это объекты, которые можно ждать с помощью оператора await. В Python есть несколько типов Awaitable объектов.
Основные типы Awaitable
import asyncio
import inspect
# 1. Coroutines (Сопрограммы)
async def my_coroutine():
await asyncio.sleep(1)
return "Done"
coro = my_coroutine()
print(asyncio.iscoroutine(coro)) # True
print(inspect.iscoroutine(coro)) # True
# 2. Tasks - обёртка над coroutine
task = asyncio.create_task(my_coroutine())
print(asyncio.iscoroutine(task)) # False
print(asyncio.isfuture(task)) # True
# 3. Futures - низкоуровневый Awaitable
future = asyncio.Future()
print(asyncio.isfuture(future)) # True
Coroutines (Сопрограммы)
import asyncio
# Coroutine создаётся с помощью async def
async def fetch_data(url: str) -> str:
await asyncio.sleep(1)
return f"Data from {url}"
# Вызов coroutine функции создаёт coroutine object
coro = fetch_data("https://example.com")
print(type(coro)) # <class "coroutine">
# Await ждёт результат
result = await fetch_data("https://example.com")
print(result) # "Data from https://example.com"
Tasks - управляемые coroutines
import asyncio
async def download(url: str):
print(f"Downloading {url}...")
await asyncio.sleep(2)
print(f"Done: {url}")
return f"Content from {url}"
async def main():
# Создание задачи - coroutine запускается в фоне
task1 = asyncio.create_task(download("url1"))
task2 = asyncio.create_task(download("url2"))
# Ждём обе задачи одновременно
results = await asyncio.gather(task1, task2)
print(results)
# Получить текущую задачу
current = asyncio.current_task()
print(f"Current task: {current.get_name()}")
asyncio.run(main())
Futures - низкоуровневые Awaitable
import asyncio
async def main():
# Future - контейнер для значения, которое будет доступно позже
future = asyncio.Future()
# Установить результат
def set_result():
future.set_result("Result set!")
asyncio.get_event_loop().call_later(1, set_result)
# Ждём результат
result = await future
print(result) # "Result set!"
asyncio.run(main())
# Future с исключением
async def future_with_error():
future = asyncio.Future()
future.set_exception(ValueError("Something went wrong"))
try:
await future
except ValueError as e:
print(f"Error: {e}")
asyncio.run(future_with_error())
Типизация Awaitable
from typing import Awaitable, Coroutine
import asyncio
# Awaitable[T] - что-то, что можно ждать и получить T
def process_awaitable(coro: Awaitable[str]) -> Awaitable[str]:
async def wrapper():
result = await coro
return f"Processed: {result}"
return wrapper()
# Coroutine[YieldType, SendType, ReturnType]
async def typed_coroutine() -> str:
return "result"
coro: Coroutine[None, None, str] = typed_coroutine()
result: str = await coro
asyncio.gather() - параллельное ожидание
import asyncio
async def task(name: str, delay: int):
print(f"Task {name} started")
await asyncio.sleep(delay)
print(f"Task {name} done")
return f"Result {name}"
async def main():
# Ждём все задачи одновременно
results = await asyncio.gather(
task("A", 1),
task("B", 2),
task("C", 1),
return_exceptions=True # Не вызывает исключение
)
print(results) # ["Result A", "Result B", "Result C"]
asyncio.run(main())
asyncio.wait() - более гибкое ожидание
import asyncio
async def main():
async def slow_task(n):
await asyncio.sleep(n)
return f"Task {n}"
tasks = [slow_task(1), slow_task(2), slow_task(3)]
# Ждём когда первая задача завершится
done, pending = await asyncio.wait(
tasks,
return_when=asyncio.FIRST_COMPLETED
)
print(f"Done: {done}")
print(f"Pending: {pending}")
# Ждём когда все завершатся
done, pending = await asyncio.wait(
tasks,
return_when=asyncio.ALL_COMPLETED
)
asyncio.run(main())
Кастомные Awaitable объекты
import asyncio
class CustomAwaitable:
def __init__(self, value):
self.value = value
def __await__(self):
# __await__ должна вернуть iterator
yield from asyncio.sleep(1).__await__()
return self.value
async def main():
result = await CustomAwaitable("Custom result")
print(result) # "Custom result"
asyncio.run(main())
asyncio.wait_for() - с timeout
import asyncio
from typing import List
async def download_file(url: str) -> str:
await asyncio.sleep(2)
return f"Content of {url}"
async def download_with_timeout(urls: List[str], timeout: int = 5):
tasks = [download_file(url) for url in urls]
try:
results = await asyncio.wait_for(
asyncio.gather(*tasks),
timeout=timeout
)
return results
except asyncio.TimeoutError:
print("Download timeout!")
for task in tasks:
if not task.done():
task.cancel()
async def main():
urls = ["url1", "url2", "url3"]
results = await download_with_timeout(urls, timeout=10)
print(results)
asyncio.run(main())
Различия между coroutine, task и future
import asyncio
async def my_coro():
return "result"
async def main():
# Coroutine - не запущен
coro = my_coro()
print(type(coro)) # <class "coroutine">
# Task - запущен в фоне
task = asyncio.create_task(my_coro())
print(type(task)) # <class "Task">
print(asyncio.isfuture(task)) # True (Task это Future)
# Future - самый низкоуровневый
future = asyncio.Future()
print(type(future)) # <class "Future">
# Все три - Awaitable, но поведение разное
print(await coro) # Работает
print(await task) # Работает
# print(await future) # Будет ждать вечно
asyncio.run(main())
Ключевые выводы
- Coroutines создаются через
async def, не запущены доawait - Tasks — это coroutines, запущенные в фоне через
asyncio.create_task() - Futures — низкоуровневые объекты для установки результатов вручную
- Все три типа — Awaitable и могут использоваться с
await - Лучшая практика: используй
asyncio.create_task()вместоasyncio.gather()для управляемости