Ответ
asyncio.Task — это объект, который планирует и управляет выполнением асинхронной функции (корутины) в цикле событий. Он позволяет запускать корутины конкурентно, не дожидаясь завершения одной, чтобы начать другую.
Ключевое отличие от прямого await:
await my_coro(): Последовательное выполнение. Программа остановится и будет ждать завершенияmy_coro(), прежде чем перейти к следующей строке кода.task = asyncio.create_task(my_coro()): Конкурентный запуск. Корутинаmy_coro()планируется для выполнения в фоновом режиме, а программа немедленно продолжает свою работу.taskможно использовать позже, чтобы дождаться результата.
Как создать Task:
Основной способ — использовать функцию asyncio.create_task().
Практический пример (конкурентное выполнение):
В этом примере две задачи запускаются практически одновременно и выполняются параллельно, а не одна за другой.
import asyncio
import time
async def say_after(delay, text):
await asyncio.sleep(delay)
print(text)
async def main():
start_time = time.time()
print(f"Начало выполнения в {time.strftime('%X')}")
# Создаем и запускаем две задачи конкурентно
task1 = asyncio.create_task(
say_after(1, 'Hello')
)
task2 = asyncio.create_task(
say_after(2, 'World')
)
# Ждем завершения обеих задач
await task1
await task2
# Альтернативный способ дождаться всех задач: await asyncio.gather(task1, task2)
end_time = time.time()
print(f"Завершено в {time.strftime('%X')}")
print(f"Общее время выполнения: {end_time - start_time:.2f} секунд")
asyncio.run(main())
# Вывод:
# Начало выполнения в 14:30:00
# Hello
# World
# Завершено в 14:30:02
# Общее время выполнения: 2.01 секунд (а не 1+2=3) Ответ 18+ 🔞
А, слушай, смотри, сейчас объясню про эти ваши asyncio.Task, а то у некоторых мозг набекрень становится, как про асинхронность заходит речь.
Представь себе, блядь, корутину — это как твой друг, который обещал принести пива. Если ты просто на него повесишь await, то будешь сидеть у подъезда, как лох, и ждать, пока он допиздуется из магазина. Ни почесаться, ни в телефон посмотреть — нихуя. Застыл, как истукан.
А вот Task — это, сука, гениальная идея. Ты этого друга с пивом в фоновый режим отправляешь. Создал задачу — task = asyncio.create_task(друг_с_пивом()) — и похуй. Пусть себе идёт. А сам в это время можешь чипсы открыть, музыку включить, ещё кого-нибудь позвать. Потом, когда захотел пить, делаешь await task и получаешь своё пиво. А если не захотел — можешь его вообще отменить, если он, мудак, слишком долго.
Короче, разница проще говоря:
await корутина()— это последовательно. Стою, жду, ебучую скуку терплю.task = asyncio.create_task(корутина())— это конкурентно. Запустил и забыл, делай дальше что хош, результат потом заберёшь.
Как создать эту самую задачу? Да элементарно, ёпта! asyncio.create_task() — твой главный инструмент.
Смотри, вот живой пример, чтобы мозг не взорвался:
Допустим, у нас две функции, которые спят и потом что-то говорят. Если делать их по очереди с await, то они сложатся, и мы будем ждать нихуя не три, а целых три секунды. Ай-яй-яй, неэффективно!
Но если завернуть их в Task — они побегут почти одновременно, и общее время будет равно времени самой долгой из них. Магия, блядь!
import asyncio
import time
async def say_after(delay, text):
await asyncio.sleep(delay) # Симулируем какую-то долгую работу, типа ждём ответа от сервера
print(text)
async def main():
start_time = time.time()
print(f"Стартанули в {time.strftime('%X')}")
# А вот тут фокус! Создаём две задачи и запускаем их КОНКУРЕНТНО!
task1 = asyncio.create_task(
say_after(1, 'Привет')
)
task2 = asyncio.create_task(
say_after(2, 'Мир')
)
# Теперь ждём, когда обе эти штуки допиздятся
await task1
await task2
# Кстати, можно было и так: await asyncio.gather(task1, task2) — одной строчкой
end_time = time.time()
print(f"Закончили в {time.strftime('%X')}")
print(f"Итого на всё проёбали: {end_time - start_time:.2f} секунды")
asyncio.run(main())
# Вывод будет примерно такой:
# Стартанули в 14:30:00
# Привет # Появилось через ~1 секунду
# Мир # Появилось через ~2 секунды ОТ НАЧАЛА, а не после "Привет"
# Закончили в 14:30:02
# Итого на всё проёбали: 2.01 секунды (ВОТ ОН, ПИЗДЕЦ КАКОЙ ВЫИГРЫШ! А не 1+2=3)
Видишь? Вместо трёх секунд — две. Потому что пока вторая задача два секунды спала, первая уже своё дело сделала и отчиталась. Вот для этого эти Task и нужны, чтобы не проёбывать время впустую, ожидая каждую операцию по отдельности.