Чем отличается корутина от задачи (task) в Python asyncio

Ответ

Основное различие заключается в том, что корутина — это определение асинхронной операции, а задача (Task) — это её запущенный на выполнение экземпляр в цикле событий.

  • Корутина (Coroutine): Объект, создаваемый при вызове функции async def. Сама по себе корутина ничего не делает, пока её не запустят с помощью await или не обернут в Task.
  • Задача (Task): Объект, который планирует выполнение корутины в цикле событий (event loop) как можно скорее. Задачи выполняются конкурентно.

Ключевые отличия:

  • Выполнение: Корутина — это "рецепт". Task — это уже запущенный "процесс" по этому рецепту.
  • Управление: Task управляется циклом событий, его можно отменить или проверить его состояние (завершен, ожидает). Корутину нужно явно запустить.
  • Создание: Задачи создаются с помощью asyncio.create_task().

Пример:

import asyncio

async def say_hello():
    print("Начало...")
    await asyncio.sleep(1)
    print("...конец!")
    return "Готово"

async def main():
    # 1. Просто создаем объект корутины. Ничего не происходит.
    coro = say_hello()
    print(f"Тип coro: {type(coro)}")

    # 2. Создаем Task. Корутина немедленно планируется к выполнению в цикле событий.
    print("Создаем задачу...")
    task = asyncio.create_task(say_hello())
    print(f"Тип task: {type(task)}")

    # Ждем завершения задачи и получаем результат
    result = await task
    print(f"Результат задачи: {result}")

asyncio.run(main())

# Вывод:
# Тип coro: <class 'coroutine'>
# Создаем задачу...
# Тип task: <class '_asyncio.Task'>
# Начало...
# ...конец!
# Результат задачи: Готово

Ответ 18+ 🔞

А, ну это, классика, блядь! Сидишь такой, читаешь документацию, а там тебе: корутина, задача, event loop... Глаза, сука, вытекают, а понять нихуя не можешь. Ёпта, давай разжую, как для дебила, но с технической точностью, блядь.

Смотри, представь себе, что корутина — это, типа, рецепт борща, написанный на бумажке. Лежит себе, пахнет чернилами, нихуя не происходит. Просто описание, что и как делать: свеклу натереть, картошку порезать, бульон сварить. Это и есть async def say_hello() — функция, которая объявляет, ЧТО делать.

А задача (Task) — это уже ты, сука, взял этот рецепт, засучил рукава и начал реально готовить этот борщ на кухне. Кастрюли греются, картошка булькает, всё в процессе. Это asyncio.create_task(say_hello()). Задача — это уже запущенный в работу процесс, которым управляет главный повар, он же цикл событий (event loop).

В чём разница, если по-простому, ёбта?

  • Корутина — это план, намерение, обещание. Сама по себе она нихуя не стоит.
  • Задача — это уже действие. Её можно отменить (сказать "хватит варить, выкинь всё"), можно проверить, готова ли она ("борщ уже?") и получить результат ("попробовать на вкус").

Вот смотри на этот код, тут всё как на ладони, блядь:

import asyncio

async def say_hello():
    print("Начало...")
    await asyncio.sleep(1)
    print("...конец!")
    return "Готово"

async def main():
    # 1. Вот это — просто создали бумажку с рецептом. Тишина, пиздец.
    coro = say_hello()
    print(f"Тип coro: {type(coro)}")  # Посмотрели на бумажку: да, это рецепт.

    # 2. А вот это — БАЦ! Бросили рецепт повару в цикл событий. Он начал готовить!
    print("Создаем задачу...")
    task = asyncio.create_task(say_hello())
    print(f"Тип task: {type(task)}")  # Посмотрели: да, это уже процесс готовки.

    # Ждём, пока повар закончит, и пробуем, что получилось.
    result = await task
    print(f"Результат задачи: {result}")

asyncio.run(main())

# Вывод:
# Тип coro: <class 'coroutine'>
# Создаем задачу...
# Тип task: <class '_asyncio.Task'>
# Начало...  # Опа, процесс пошёл!
# ...конец! # Готово!
# Результат задачи: Готово

Видишь? Пока мы просто объявили coro — нихуя не произошло, тишина. Как только создали task — сразу же началось выполнение, напечаталось "Начало...". Потому что задача сразу же встала в очередь к циклу событий, и он её запустил, как только смог.

Вот и вся магия, блядь. Не путай бумажку с рецептом и реальный процесс готовки, а то так и будешь сидеть голодный, с кучей coroutine объектов, которые нихуя не делают, пока ты их не запустишь через await или не завернёшь в Task.