Ответ
await
— это ключевое слово в Python, используемое в асинхронном программировании для приостановки выполнения текущей корутины (функции, объявленной с async def
) до завершения другой "awaitable" операции. Это позволяет программе эффективно использовать время ожидания, не блокируя основной поток выполнения.
Почему await
важен?
В традиционном синхронном коде, когда функция выполняет долгую операцию (например, сетевой запрос, чтение файла), весь поток выполнения блокируется до её завершения. await
решает эту проблему:
- Неблокирующее ожидание: Когда корутина встречает
await
, она приостанавливает своё выполнение и передаёт управление обратно в цикл событий (event loop). - Конкурентность: Цикл событий может использовать это время для выполнения других задач, пока ожидаемая операция не завершится. Как только ожидаемая операция готова, цикл событий возобновляет выполнение приостановленной корутины. Это позволяет эффективно обрабатывать множество I/O-связанных задач одновременно, значительно улучшая отзывчивость и пропускную способность приложений.
Пример использования:
import asyncio
async def fetch_data(delay: int, name: str) -> str:
"""Имитирует асинхронную загрузку данных."""
print(f"[{name}] Начало загрузки данных (ожидание {delay} сек)...")
await asyncio.sleep(delay) # Приостановка выполнения, управление передаётся event loop
print(f"[{name}] Данные загружены.")
return f"Результат от {name}"
async def main():
print("Запуск основной программы.")
# Запускаем две задачи конкурентно
task1 = asyncio.create_task(fetch_data(2, "Задача 1"))
task2 = asyncio.create_task(fetch_data(1, "Задача 2"))
# Ожидаем завершения обеих задач
result1 = await task1
result2 = await task2
print(f"Получено: {result1}")
print(f"Получено: {result2}")
print("Основная программа завершена.")
if __name__ == "__main__":
asyncio.run(main())
Вывод при выполнении:
Запуск основной программы.
[Задача 1] Начало загрузки данных (ожидание 2 сек)...
[Задача 2] Начало загрузки данных (ожидание 1 сек)...
[Задача 2] Данные загружены.
[Задача 1] Данные загружены.
Получено: Результат от Задача 1
Получено: Результат от Задача 2
Основная программа завершена.
Обратите внимание, что "Задача 2" завершилась раньше, хотя "Задача 1" была запущена первой. Это демонстрирует неблокирующий характер await
.
Ключевые особенности:
- Только внутри
async def
:await
может быть использован только внутри функций, объявленных сasync def
. - Ожидание "awaitable" объектов:
await
может ожидать корутины, объектыFuture
, или другие объекты, реализующие протоколawaitable
(например,asyncio.sleep()
). - Возврат корутины: Если вы забудете использовать
await
перед вызовомasync def
функции, она не выполнится, а просто вернёт объект корутины. Это частая ошибка, которая может привести к незаметным багам. - Не блокирует поток:
await
не блокирует операционную систему или поток выполнения, а лишь приостанавливает текущую корутину, позволяя циклу событий переключиться на другие задачи.