Почему функции asyncio.current_task() не удается передать?

Как модифицировать функцию `info_start_tasks`, чтобы ошибка 'NoneType' object has no attribute 'cancel' в строке `task.cancel()` не возникала при условии, что параметр `next_stage` не равен `None`? Я также хочу, чтобы отложенные сообщения, отправляемые через `asyncio.sleep`, не сбрасывались при вызове функции с `next_stage!=None`.
  • 23 апреля 2024 г. 13:50
Ответы на вопрос 2
Ошибка 'NoneType' object has no attribute 'cancel' возникает потому, что функция asyncio.current_task() может вернуть None, если код выполняется не в контексте задачи asyncio. Поэтому нужно проверять перед вызовом метода cancel(), что переменная task не является None.

Для модификации функции `info_start_tasks` можно переписать ее следующим образом:

```python
import asyncio

async def info_start_tasks(next_stage=None):
    tasks = []

    # Создаем отложенные сообщения
    for i in range(3):
        msg = f"Message {i+1}"
        tasks.append(asyncio.create_task(print_message(msg)))

    # Если задан параметр next_stage, запускаем следующий этап
    if next_stage:
        await asyncio.sleep(5)
        async with next_stage:
            # Добавляем проверку на None перед отменой задачи
            for task in tasks:
                if task:
                    task.cancel()

async def print_message(msg):
    await asyncio.sleep(1)
    print(msg)

# Пример вызова функции
asyncio.run(info_start_tasks(next_stage=True))
```

В этой версии функции `info_start_tasks` добавлена проверка на None перед вызовом метода cancel() для каждой задачи в списке tasks. Также добавлено условие, что если параметр next_stage не равен None, то отложенные сообщения не будут сброшены при вызове функции с next_stage=True.
Цитата из документации : 
Return the currently running Task instance, or None if no task is running.

Как я это понимаю, если ты запланировал выполнение функции как задачи через asyncio.create_task(), то эта функция, и все, вызываемые в ней, смогут получить объект задачи, вызвав asyncio.current_task().
Если же управление в текущую функции было передано без использования задач на любом из уровней, только через await вызовы, то current_task() вернёт None.
Похожие вопросы