Asyncio.create task: примеры (PYTHON)

Использование asyncio.create_task для асинхронного выполнения в Python
Раздел: Асинхронное программирование, Управление задачами
asyncio.create_task(coro: coroutine): asyncio.Task

Базовое описание функции asyncio.create_task

Функция asyncio.create_task() представляет инструмент для запуска корутин в качестве асинхронных задач внутри цикла событий. Использование этой функции позволяет выполнять несколько корутин конкурентно, не дожидаясь завершения каждой по отдельности.

Применение функции наблюдается в ситуациях, когда требуется параллельное выполнение нескольких асинхронных операций, например, одновременные сетевые запросы, обработка файлов или взаимодействие с периферийными устройствами.

Аргументы функции

  • coro: обязательный аргумент, представляющий корутину для выполнения.
  • name: необязательный аргумент строкового типа для присвоения имени задаче. Появился в Python 3.8.
  • context: необязательный аргумент, позволяющий передавать контекст выполнения (например, для contextvars). Добавлен в Python 3.11.

Возвращаемое значение

Функция возвращает объект типа Task, который является подклассом Future. Этот объект позволяет управлять выполнением задачи, ожидать её завершения или отменять выполнение.

Примеры использования asyncio.create_task

Базовый пример создания и выполнения задачи:

import asyncio

async def example_coroutine():
    await asyncio.sleep(1)
    return "Результат"

async def main():
    task = asyncio.create_task(example_coroutine())
    result = await task
    print(result)

asyncio.run(main())
Результат

Пример с именем задачи:

async def main():
    task = asyncio.create_task(
        example_coroutine(), 
        name="MyTask"
    )
    print(f"Имя задачи: {task.get_name()}")
    await task

asyncio.run(main())
Имя задачи: MyTask

Альтернативные функции в Python

  • asyncio.ensure_future(): функция создает задачу из различных объектов, включая корутины, Future и awaitable-объекты. Отличие от create_task заключается в более широкой области применения, но меньшей эффективности для корутин.
  • asyncio.gather(): функция позволяет запустить несколько корутин параллельно и собрать их результаты. Использование предпочтительно при необходимости ожидания завершения группы задач.
  • asyncio.wait(): функция обеспечивает ожидание завершения задач с возможностью установки условий завершения. Применение полезно при работе с динамическим набором задач.

Аналоги в других языках программирования

JavaScript: использование Promise и async/await с запуском через микрозадачи.

async function example() {
    return "Done";
}

const task = example();
task.then(result => console.log(result));
Done

Go: горутины запускаются с помощью ключевого слова go.

package main

import (
    "fmt"
    "time"
)

func example() {
    fmt.Println("Выполнено")
}

func main() {
    go example()
    time.Sleep(time.Second)
}
Выполнено

Kotlin: корутины запускаются через launch или async в области видимости.

import kotlinx.coroutines.*

fun main() = runBlocking {
    val task = launch {
        delay(1000)
        println("Завершено")
    }
    task.join()
}
Завершено

Типичные ошибки при использовании

Отсутствие ожидания выполнения задачи приводит к незавершению программы:

async def main():
    asyncio.create_task(example_coroutine())
    # Задача может не успеть выполниться

asyncio.run(main())
Программа завершается без вывода

Попытка создания задачи вне цикла событий вызывает ошибку:

task = asyncio.create_task(example_coroutine())  # Ошибка!
RuntimeError: no running event loop

Изменения в последних версиях Python

  • Python 3.8: добавлен параметр name для именования задач.
  • Python 3.11: введен параметр context для управления контекстом выполнения. Добавлена возможность отмены задач по группам через asyncio.TaskGroup.
  • Python 3.12: улучшена производительность и отладка задач.

Расширенные примеры применения

Создание нескольких задач с обработкой исключений:

Пример python
async def risky_coroutine(id):
    if id == 2:
        raise ValueError(f"Ошибка в задаче {id}")
    return f"Успех {id}"

async def main():
    tasks = [
        asyncio.create_task(risky_coroutine(i))
        for i in range(4)
    ]
    for task in tasks:
        try:
            result = await task
            print(result)
        except ValueError as e:
            print(f"Поймано исключение: {e}")

asyncio.run(main())
Успех 0
Успех 1
Поймано исключение: Ошибка в задаче 2
Успех 3

Использование контекста выполнения:

Пример python
import contextvars

ctx_var = contextvars.ContextVar('var', default='default')

async def context_aware():
    print(f"Значение: {ctx_var.get()}")

async def main():
    ctx_var.set('основной')
    task_ctx = contextvars.copy_context()
    ctx_var.set('измененный')
    
    task = asyncio.create_task(
        context_aware(),
        context=task_ctx
    )
    await task

asyncio.run(main())
Значение: основной

питон asyncio.create_task function comments

En
Asyncio.create task Wrap a coroutine into a Task and schedule its execution