> **Источник:** https://python-all.ru/3.7/library/asyncio-task.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# Корутины и задачи

В этом разделе представлены высокоуровневые API asyncio для работы с корутинами и задачами.

- [Корутины](https://python-all.ru/3.7/library/asyncio-task.html#coroutines)
- [Ожидаемые объекты](https://python-all.ru/3.7/library/asyncio-task.html#awaitables)
- [Запуск asyncio-программы](https://python-all.ru/3.7/library/asyncio-task.html#running-an-asyncio-program)
- [Создание задач](https://python-all.ru/3.7/library/asyncio-task.html#creating-tasks)
- [Приостановка выполнения](https://python-all.ru/3.7/library/asyncio-task.html#sleeping)
- [Одновременное выполнение задач](https://python-all.ru/3.7/library/asyncio-task.html#running-tasks-concurrently)
- [Защита от отмены](https://python-all.ru/3.7/library/asyncio-task.html#shielding-from-cancellation)
- [Тайм-ауты](https://python-all.ru/3.7/library/asyncio-task.html#timeouts)
- [Примитивы ожидания](https://python-all.ru/3.7/library/asyncio-task.html#waiting-primitives)
- [Планирование из других потоков](https://python-all.ru/3.7/library/asyncio-task.html#scheduling-from-other-threads)
- [Интроспекция](https://python-all.ru/3.7/library/asyncio-task.html#introspection)
- [Объект задачи](https://python-all.ru/3.7/library/asyncio-task.html#task-object)
- [Корутины на основе генераторов](https://python-all.ru/3.7/library/asyncio-task.html#generator-based-coroutines)

## [Корутины](https://python-all.ru/3.7/library/asyncio-task.html#id1)

Корутины, объявленные с помощью синтаксиса async/await, являются предпочтительным способом написания приложений asyncio. Например, следующий фрагмент кода (требуется Python 3.7+) выводит «hello», ждёт 1 секунду, а затем выводит «world»:

```python
>>> import asyncio

>>> async def main():
...     print('hello')
...     await asyncio.sleep(1)
...     print('world')

>>> asyncio.run(main())
hello
world
```

Обратите внимание, что простой вызов корутины не запланирует её выполнение:

```python
>>> main()
<coroutine object main at 0x1053bb7c8>
```

Для фактического запуска корутины asyncio предоставляет три основных механизма:

- Функция [`asyncio.run()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.run) для запуска точки входа верхнего уровня – функции «main()» (см. пример выше.)
- Ожидание корутины. Следующий фрагмент кода выведет «hello» после ожидания в 1 секунду, а затем выведет «world» после ожидания *ещё* 2 секунд:

  ```python
  import asyncio
  import time

  async def say_after(delay, what):
      await asyncio.sleep(delay)
      print(what)

  async def main():
      print(f"started at {time.strftime('%X')}")

      await say_after(1, 'hello')
      await say_after(2, 'world')

      print(f"finished at {time.strftime('%X')}")

  asyncio.run(main())
  ```

  Ожидаемый вывод:

  ```python
  started at 17:13:52
  hello
  world
  finished at 17:13:55
  ```
- Функция [`asyncio.create_task()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.create_task) для параллельного запуска корутин в качестве asyncio [`Tasks`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task).

  Давайте изменим пример выше и запустим две `say_after` корутины *параллельно*:

  ```python
  async def main():
      task1 = asyncio.create_task(
          say_after(1, 'hello'))

      task2 = asyncio.create_task(
          say_after(2, 'world'))

      print(f"started at {time.strftime('%X')}")

      # Ожидать завершения обеих задач (должно занять
      # около 2 секунд).
      await task1
      await task2

      print(f"finished at {time.strftime('%X')}")
  ```

  Обратите внимание, что ожидаемый вывод теперь показывает, что фрагмент выполняется на 1 секунду быстрее, чем раньше:

  ```python
  started at 17:14:32
  hello
  world
  finished at 17:14:34
  ```

## [Ожидаемые объекты](https://python-all.ru/3.7/library/asyncio-task.html#id2)

Говорят, что объект является **ожидаемым** объектом, если его можно использовать в выражении [`await`](https://python-all.ru/3.7/reference/expressions.html#await). Многие API asyncio предназначены для принятия ожидаемых объектов.

Существует три основных типа *ожидаемых* объектов: **корутины**, **задачи** и **future**.

Корутины

Корутины Python являются *ожидаемыми объектами*, а значит, их можно ожидать из других корутин:

```python
import asyncio

async def nested():
    return 42

async def main():
    # Если просто вызвать "nested()", ничего не произойдет.
    # Создается объект корутины, но он не ожидается,
    # поэтому он *вообще не выполнится*.
    nested()

    # Давайте поступим иначе и теперь ожидаем его:
    print(await nested())  # выведет "42".

asyncio.run(main())
```

> **Важно**
>
> В данной документации термин «корутина» может использоваться для двух тесно связанных понятий:
>
> - *корутинная функция*: функция [`async def`](https://python-all.ru/3.7/reference/compound_stmts.html#async-def);
> - *объект корутины*: объект, возвращаемый при вызове *корутинной функции*.

asyncio также поддерживает устаревшие [корутины на основе генераторов](https://python-all.ru/3.7/library/asyncio-task.html#asyncio-generator-based-coro).

Задачи

*Задачи* используются для планирования корутин *параллельно*.

Когда корутина обёрнута в *задачу* с помощью таких функций, как [`asyncio.create_task()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.create_task), корутина автоматически планируется к скорому выполнению:

```python
import asyncio

async def nested():
    return 42

async def main():
    # Запланировать выполнение nested() вскоре конкурентно
    # с "main()".
    task = asyncio.create_task(nested())

    # "задача" теперь можно использовать для отмены "nested()" или
    # можно просто применить await, чтобы дождаться завершения:
    await task

asyncio.run(main())
```

Future

[`Future`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future) – это специальный **низкоуровневый** ожидаемый объект, который представляет **конечный результат** асинхронной операции.

Когда объект Future *ожидается*, это означает, что корутина будет ожидать, пока Future не будет разрешён в каком-то другом месте.

Объекты Future в asyncio необходимы для того, чтобы код, основанный на колбэках, мог использоваться с async/await.

Обычно **нет необходимости** создавать объекты Future в коде уровня приложения.

Объекты Future, иногда предоставляемые библиотеками и некоторыми API asyncio, можно ожидать (await):

```python
async def main():
    await function_that_returns_a_future_object()

    # это также допустимо:
    await asyncio.gather(
        function_that_returns_a_future_object(),
        some_python_coroutine()
    )
```

Хороший пример низкоуровневой функции, возвращающей объект Future – [`loop.run_in_executor()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.run_in_executor).

## [Запуск программы asyncio](https://python-all.ru/3.7/library/asyncio-task.html#id3)

#### `asyncio.run(coro, *, debug=False)`

Выполняет [корутину](https://python-all.ru/3.7/glossary.html#term-coroutine) *coro* и возвращает результат.

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

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

Если *debug* равно `True`, цикл событий будет запущен в режиме отладки.

Эта функция всегда создаёт новый цикл событий и закрывает его в конце. Её следует использовать в качестве главной точки входа для программ asyncio, и в идеале она должна вызываться только один раз.

Пример:

```python
async def main():
    await asyncio.sleep(1)
    print('hello')

asyncio.run(main())
```

Новое в версии 3.7: **Важно:** эта функция была добавлена в asyncio в Python 3.7 на [временной основе](https://python-all.ru/3.7/glossary.html#term-provisional-api).

## [Создание задач](https://python-all.ru/3.7/library/asyncio-task.html#id4)

#### `asyncio.create_task(coro)`

Wrap the *coro* [coroutine](https://python-all.ru/3.7/library/asyncio-task.html#coroutine) into a [`Task`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task) and schedule its execution. Return the Task object.

Задача выполняется в цикле, возвращаемом [`get_running_loop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.get_running_loop); [`RuntimeError`](https://python-all.ru/3.7/library/exceptions.html#RuntimeError) возбуждается, если в текущем потоке нет запущенного цикла.

Эта функция была **добавлена в Python 3.7**. До Python 3.7 вместо неё можно использовать низкоуровневую функцию [`asyncio.ensure_future()`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.ensure_future):

```python
async def coro():
    ...

# В Python 3.7+
task = asyncio.create_task(coro())
...

# Это работает во всех версиях Python, но менее читаемо
task = asyncio.ensure_future(coro())
...
```

Добавлено в версии 3.7.

## [Ожидание](https://python-all.ru/3.7/library/asyncio-task.html#id5)

#### `coroutine asyncio.sleep(delay, result=None, *, loop=None)`

Приостанавливает выполнение на *delay* секунд.

Если *result* указан, он возвращается вызывающей стороне после завершения корутины.

`sleep()` всегда приостанавливает текущую задачу, позволяя выполняться другим задачам.

Аргумент *loop* устарел и будет удалён в Python 3.10.

Пример корутины, выводящей текущую дату каждую секунду в течение 5 секунд:

```python
import asyncio
import datetime

async def display_date():
    loop = asyncio.get_running_loop()
    end_time = loop.time() + 5.0
    while True:
        print(datetime.datetime.now())
        if (loop.time() + 1.0) >= end_time:
            break
        await asyncio.sleep(1)

asyncio.run(display_date())
```

## [Одновременный запуск задач](https://python-all.ru/3.7/library/asyncio-task.html#id6)

#### `awaitable asyncio.gather(*aws, loop=None, return_exceptions=False)`

Выполняет [ожидаемые объекты](https://python-all.ru/3.7/library/asyncio-task.html#asyncio-awaitables) из последовательности *aws* *одновременно*.

Если любой ожидаемый объект из *aws* является корутиной, он автоматически планируется как задача.

Если все ожидаемые объекты завершены успешно, результатом является сводный список возвращённых значений. Порядок значений результата соответствует порядку ожидаемых объектов в *aws*.

Если *return\_exceptions* равно `False` (по умолчанию), первое возбуждённое исключение немедленно распространяется на задачу, ожидающую `gather()`. Остальные ожидаемые объекты в последовательности *aws* **не будут отменены** и продолжат выполнение.

Если *return\_exceptions* равно `True`, исключения обрабатываются так же, как успешные результаты, и объединяются в списке результатов.

Если `gather()` *отменён*, все переданные ожидаемые объекты (которые ещё не завершились) также *отменяются*.

Если любая задача или Future из последовательности *aws* *отменена*, это рассматривается так, как если бы она возбудила [`CancelledError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.CancelledError) – вызов `gather()` в этом случае **не** отменяется. Это сделано для предотвращения ситуации, когда отмена одной переданной задачи или Future приводит к отмене других задач или Future.

Пример:

```python
import asyncio

async def factorial(name, number):
    f = 1
    for i in range(2, number + 1):
        print(f"Task {name}: Compute factorial({i})...")
        await asyncio.sleep(1)
        f *= i
    print(f"Task {name}: factorial({number}) = {f}")

async def main():
    # Запланировать три вызова *конкурентно*:
    await asyncio.gather(
        factorial("A", 2),
        factorial("B", 3),
        factorial("C", 4),
    )

asyncio.run(main())

# Ожидаемый вывод:
#
#     Задача A: вычислить factorial(2)...
#     Задача B: вычислить factorial(2)...
#     Задача C: вычислить factorial(2)...
#     Задача A: factorial(2) = 2
#     Задача B: вычислить factorial(3)...
#     Задача C: вычислить factorial(3)...
#     Задача B: factorial(3) = 6
#     Задача C: вычислить factorial(4)...
#     Задача C: factorial(4) = 24
```

Изменено в версии 3.7: Если сам *gather* отменён, отмена распространяется независимо от *return\_exceptions*.

## [Защита от отмены](https://python-all.ru/3.7/library/asyncio-task.html#id7)

#### `awaitable asyncio.shield(aw, *, loop=None)`

Защищает [ожидаемый объект](https://python-all.ru/3.7/library/asyncio-task.html#asyncio-awaitables) от [`cancelled`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task.cancel).

Если *aw* является корутиной, она автоматически планируется как задача.

Выражение:

```python
res = await shield(something())
```

эквивалентно:

```python
res = await something()
```

*За исключением* того, что если содержащая его корутина отменяется, задача, выполняющаяся в `something()`, не отменяется. С точки зрения `something()` отмена не произошла. Хотя её вызывающий код всё ещё отменён, поэтому выражение «await» по-прежнему возбуждает [`CancelledError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.CancelledError).

Если `something()` отменяется другими средствами (т.е. изнутри самой себя), это также отменит `shield()`.

Если требуется полностью игнорировать отмену (не рекомендуется), функцию `shield()` следует комбинировать с конструкцией try/except следующим образом:

```python
try:
    res = await shield(something())
except CancelledError:
    res = None
```

## [Тайм-ауты](https://python-all.ru/3.7/library/asyncio-task.html#id8)

#### `coroutine asyncio.wait_for(aw, timeout, *, loop=None)`

Ожидает завершения *aw* [ожидаемого объекта](https://python-all.ru/3.7/library/asyncio-task.html#asyncio-awaitables) с таймаутом.

Если *aw* является корутиной, она автоматически планируется как задача.

*timeout* может быть либо `None`, либо числом с плавающей запятой или целым числом секунд ожидания. Если *timeout* равно `None`, блокирует выполнение до завершения future.

Если происходит таймаут, он отменяет задачу и возбуждает [`asyncio.TimeoutError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.TimeoutError).

Чтобы избежать задачи [`cancellation`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task.cancel), оберните её в [`shield()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.shield).

Функция будет ждать, пока future не будет фактически отменён, поэтому общее время ожидания может превысить *тайм-аут*.

Если ожидание отменяется, future *aw* также отменяется.

Аргумент *loop* устарел и будет удалён в Python 3.10.

Пример:

```python
async def eternity():
    # Спать в течение часа
    await asyncio.sleep(3600)
    print('yay!')

async def main():
    # Ждать не более 1 секунды
    try:
        await asyncio.wait_for(eternity(), timeout=1.0)
    except asyncio.TimeoutError:
        print('timeout!')

asyncio.run(main())

# Ожидаемый вывод:
#
#     тайм-аут!
```

Изменено в версии 3.7: Когда *aw* отменяется из-за таймаута, `wait_for` ожидает отмены *aw*. Ранее оно немедленно вызывало [`asyncio.TimeoutError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.TimeoutError).

## [Примитивы ожидания](https://python-all.ru/3.7/library/asyncio-task.html#id9)

#### `coroutine asyncio.wait(aws, *, loop=None, timeout=None, return_when=ALL_COMPLETED)`

Запускает [ожидаемые объекты](https://python-all.ru/3.7/library/asyncio-task.html#asyncio-awaitables) из набора *aws* конкурентно и блокируется до выполнения условия, заданного *return\_when*.

Если любой ожидаемый объект в *aws* является корутиной, он автоматически планируется как задача. Передача объектов-корутин напрямую в `wait()` устарела, так как приводит к [запутанному поведению](https://python-all.ru/3.7/library/asyncio-task.html#asyncio-example-wait-coroutine).

Возвращает два набора задач/future: `(done, pending)`.

Использование:

```python
done, pending = await asyncio.wait(aws)
```

Аргумент *loop* устарел и будет удалён в Python 3.10.

*timeout* (число с плавающей точкой или целое) позволяет указать максимальное время ожидания в секундах перед возвратом результата.

Обратите внимание, что эта функция не вызывает [`asyncio.TimeoutError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.TimeoutError). Объекты Future или задачи, не завершённые к моменту таймаута, просто возвращаются во втором наборе.

*return\_when* указывает, когда эта функция должна вернуть результат. Это должна быть одна из следующих констант:

| Константа | Описание |
| --- | --- |
| `FIRST_COMPLETED` | Функция вернёт результат, когда любой future завершится или будет отменён. |
| `FIRST_EXCEPTION` | Функция вернёт результат, когда любой future завершится, возбудив исключение. Если ни один future не возбудит исключение, это эквивалентно `ALL_COMPLETED`. |
| `ALL_COMPLETED` | Функция вернёт результат, когда все future завершатся или будут отменены. |

В отличие от [`wait_for()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.wait_for), `wait()` не отменяет futures при возникновении таймаута.

> **Примечание**
>
> `wait()` автоматически планирует корутины как задачи и затем возвращает эти неявно созданные объекты задач в `(done, pending)` наборах. Поэтому следующий код не будет работать, как ожидается:
>
> ```python
> async def foo():
>     return 42
>
> coro = foo()
> done, pending = await asyncio.wait({coro})
>
> if coro in done:
>     # Эта ветка никогда не будет выполнена!
> ```
>
> Вот как можно исправить приведённый выше фрагмент:
>
> ```python
> async def foo():
>     return 42
>
> task = asyncio.create_task(foo())
> done, pending = await asyncio.wait({task})
>
> if task in done:
>     # Теперь всё будет работать как ожидается.
> ```
>
> Передача объектов-корутин напрямую в `wait()` устарела.

#### `asyncio.as_completed(aws, *, loop=None, timeout=None)`

Выполняет [ожидаемые объекты](https://python-all.ru/3.7/library/asyncio-task.html#asyncio-awaitables) из набора *aws* конкурентно. Возвращает итератор объектов [`Future`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future). Каждый возвращённый объект Future представляет собой самый ранний результат из оставшихся ожидаемых объектов.

Вызывает [`asyncio.TimeoutError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.TimeoutError), если время ожидания истекает до того, как все Future будут завершены.

Пример:

```python
for f in as_completed(aws):
    earliest_result = await f
    # ...
```

## [Планирование из других потоков](https://python-all.ru/3.7/library/asyncio-task.html#id10)

#### `asyncio.run_coroutine_threadsafe(coro, loop)`

Отправляет корутину в указанный цикл событий. Потокобезопасно.

Возвращает [`concurrent.futures.Future`](https://python-all.ru/3.7/library/concurrent.futures.html#concurrent.futures.Future) для ожидания результата из другого потока операционной системы.

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

```python
# Создать корутину
coro = asyncio.sleep(1, result=3)

# Отправить корутину в заданный цикл
future = asyncio.run_coroutine_threadsafe(coro, loop)

# Ожидать результат с необязательным аргументом таймаута
assert future.result(timeout) == 3
```

Если в корутине возникло исключение, возвращаемый объект Future получит уведомление. Его также можно использовать для отмены задачи в цикле событий:

```python
try:
    result = future.result(timeout)
except asyncio.TimeoutError:
    print('The coroutine took too long, cancelling the task...')
    future.cancel()
except Exception as exc:
    print(f'The coroutine raised an exception: {exc!r}')
else:
    print(f'The coroutine returned: {result!r}')
```

См. раздел [concurrency and multithreading](https://python-all.ru/3.7/library/asyncio-dev.html#asyncio-multithreading) документации.

В отличие от других функций asyncio, эта функция требует явной передачи аргумента *loop* .

Новое в версии 3.5.1.

## [Интроспекция](https://python-all.ru/3.7/library/asyncio-task.html#id11)

#### `asyncio.current_task(loop=None)`

Возвращает экземпляр текущей выполняющейся [`Task`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task) или `None`, если нет выполняющейся задачи.

Если *loop* равен `None`, используется [`get_running_loop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.get_running_loop) для получения текущего цикла.

Добавлено в версии 3.7.

#### `asyncio.all_tasks(loop=None)`

Возвращает набор ещё не завершённых объектов [`Task`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task), выполняемых циклом.

Если *loop* равен `None`, [`get_running_loop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.get_running_loop) используется для получения текущего цикла.

Добавлено в версии 3.7.

## [Объект Задачи](https://python-all.ru/3.7/library/asyncio-task.html#id12)

#### `class asyncio.Task(coro, *, loop=None)`

Объект [`Future-like`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future), выполняющий корутину Python [корутину](https://python-all.ru/3.7/library/asyncio-task.html#coroutine). Непотокобезопасный.

Задачи используются для выполнения корутин в циклах событий. Если корутина ожидает Future, задача приостанавливает выполнение корутины и ждёт завершения Future. Когда Future *завершён*, выполнение обёрнутой корутины возобновляется.

Циклы событий используют кооперативное планирование: цикл событий выполняет по одной задаче за раз. Пока задача ожидает завершения Future, цикл событий выполняет другие задачи, колбэки или производит операции ввода-вывода.

Используйте высокоуровневую функцию [`asyncio.create_task()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.create_task) для создания задач или низкоуровневые функции [`loop.create_task()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.loop.create_task) или [`ensure_future()`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.ensure_future). Ручное создание экземпляров задач не рекомендуется.

Чтобы отменить выполняющуюся задачу, используйте метод [`cancel()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task.cancel). Его вызов приведёт к тому, что задача возбудит исключение [`CancelledError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.CancelledError) в обёрнутой корутине. Если во время отмены корутина ожидает объект Future, этот объект Future будет отменён.

[`cancelled()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task.cancelled) можно использовать для проверки, была ли задача отменена. Метод возвращает `True`, если обёрнутая корутина не подавила исключение [`CancelledError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.CancelledError) и была действительно отменена.

[`asyncio.Task`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task) наследует от [`Future`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future) все свои API, за исключением [`Future.set_result()`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future.set_result) и [`Future.set_exception()`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future.set_exception).

Задачи поддерживают модуль [`contextvars`](https://python-all.ru/3.7/library/contextvars.html#module-contextvars). Когда создаётся задача,\\nона копирует текущий контекст и затем выполняет свою\\nкорутину в скопированном контексте.

Изменено в версии 3.7: Добавлена поддержка модуля [`contextvars`](https://python-all.ru/3.7/library/contextvars.html#module-contextvars).

#### `cancel()`

Запрашивает отмену задачи.

Обеспечивает выброс исключения [`CancelledError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.CancelledError) в обёрнутую корутину на следующем цикле событийного цикла.

Затем корутина имеет возможность очистить ресурсы или даже отклонить\\nзапрос, подавив исключение с помощью блока [`try`](https://python-all.ru/3.7/reference/compound_stmts.html#try) …\\n… `except CancelledError` … [`finally`](https://python-all.ru/3.7/reference/compound_stmts.html#finally).\\nПоэтому, в отличие от [`Future.cancel()`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future.cancel), [`Task.cancel()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task.cancel) не\\nгарантирует, что задача будет отменена, хотя полное подавление отмены\\nне является распространённой практикой и активно не рекомендуется.

Следующий пример показывает, как корутины могут перехватить запрос отмены:

```python
async def cancel_me():
    print('cancel_me(): before sleep')

    try:
        # Ждать 1 час
        await asyncio.sleep(3600)
    except asyncio.CancelledError:
        print('cancel_me(): cancel sleep')
        raise
    finally:
        print('cancel_me(): after sleep')

async def main():
    # Создать задачу "cancel_me"
    task = asyncio.create_task(cancel_me())

    # Ждать 1 секунду
    await asyncio.sleep(1)

    task.cancel()
    try:
        await task
    except asyncio.CancelledError:
        print("main(): cancel_me is cancelled now")

asyncio.run(main())

# Ожидаемый вывод:
#
#     cancel_me(): перед сном
#     cancel_me(): отмена сна
#     cancel_me(): после сна
#     main(): cancel_me теперь отменён
```

#### `cancelled()`

Return `True` if the Task is *cancelled*.

The Task is *cancelled* when the cancellation was requested with [`cancel()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task.cancel) and the wrapped coroutine propagated the [`CancelledError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.CancelledError) exception thrown into it.

#### `done()`

Возвращает `True`, если задача *завершена*.

Задача *завершена*, когда обёрнутая корутина вернула значение, возбудила исключение или задача была отменена.

#### `result()`

Возвращает результат задачи.

Если задача *завершена*, возвращается результат обёрнутой корутины (или, если корутина возбудила исключение, это исключение возбуждается повторно).

Если задача была *отменена*, этот метод возбуждает исключение [`CancelledError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.CancelledError).

Если результат задачи ещё не доступен, этот метод возбуждает исключение [`InvalidStateError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.InvalidStateError).

#### `exception()`

Возвращает исключение задачи.

Если обёрнутая корутина возбудила исключение, возвращается это исключение. Если корутина завершилась нормально, этот метод возвращает `None`.

Если задача была *отменена*, этот метод возбуждает исключение [`CancelledError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.CancelledError).

Если задача ещё не *завершена*, этот метод возбуждает исключение [`InvalidStateError`](https://python-all.ru/3.7/library/asyncio-exceptions.html#asyncio.InvalidStateError).

#### `add_done_callback(callback, *, context=None)`

Добавляет колбэк, который будет выполнен, когда задача *завершена*.

Этот метод следует использовать только в низкоуровневом коде, основанном на колбэках.

Подробнее см. в документации [`Future.add_done_callback()`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future.add_done_callback).

#### `remove_done_callback(callback)`

Удаляет *колбэк* из списка колбэков.

Этот метод следует использовать только в низкоуровневом коде, основанном на колбэках.

Подробнее см. в документации [`Future.remove_done_callback()`](https://python-all.ru/3.7/library/asyncio-future.html#asyncio.Future.remove_done_callback).

#### `get_stack(*, limit=None)`

Возвращает список кадров стека для этой задачи.

Если обёрнутая корутина не завершена, возвращается стек, в котором она приостановлена. Если корутина успешно завершилась или была отменена, возвращается пустой список. Если корутина была завершена исключением, возвращается список кадров трассировки.

Кадры всегда упорядочены от старых к новым.

Для приостановленной корутины возвращается только один кадр стека.

Необязательный аргумент *limit* задаёт максимальное количество возвращаемых кадров; по умолчанию возвращаются все доступные кадры. Порядок возвращаемого списка различается в зависимости от того, возвращается стек или трассировка: возвращаются новейшие кадры стека, но старейшие кадры трассировки. (Это соответствует поведению модуля traceback.)

#### `print_stack(*, limit=None, file=None)`

Печатает стек или трассировку для этой задачи.

Результат аналогичен выводу модуля traceback для кадров, полученных с помощью [`get_stack()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task.get_stack).

Аргумент *limit* передаётся непосредственно в [`get_stack()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.Task.get_stack).

Аргумент *file* – это поток ввода-вывода, в который записывается вывод; по умолчанию вывод записывается в [`sys.stderr`](https://python-all.ru/3.7/library/sys.html#sys.stderr).

#### `classmethod all_tasks(loop=None)`

Возвращает набор всех задач для цикла событий.

По умолчанию возвращаются все задачи для текущего цикла событий. Если *loop* равен `None`, для получения текущего цикла используется функция [`get_event_loop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.get_event_loop).

Этот метод **устарел** и будет удалён в Python 3.9. Вместо него используйте функцию [`asyncio.all_tasks()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.all_tasks).

#### `classmethod current_task(loop=None)`

Возвращает текущую выполняющуюся задачу или `None`.

Если *loop* равен `None`, для получения текущего цикла используется функция [`get_event_loop()`](https://python-all.ru/3.7/library/asyncio-eventloop.html#asyncio.get_event_loop).

Этот метод **устарел** и будет удалён в Python 3.9. Вместо него используйте функцию [`asyncio.current_task()`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.current_task).

## [Корутины на основе генераторов](https://python-all.ru/3.7/library/asyncio-task.html#id13)

> **Примечание**
>
> Поддержка корутин на основе генераторов **устарела** и запланирована к удалению в Python 3.10.

Корутины на основе генераторов предшествуют синтаксису async/await. Они представляют собой генераторы Python, использующие выражения `yield from` для ожидания Future и других корутин.

Корутины на основе генераторов следует декорировать с помощью [`@asyncio.coroutine`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.coroutine), хотя это не требуется.

#### `@asyncio.coroutine`

Декоратор для пометки корутин на основе генераторов.

Этот декоратор позволяет старым корутинам на основе генераторов быть совместимыми с кодом async/await:

```python
@asyncio.coroutine
def old_style_coroutine():
    yield from asyncio.sleep(1)

async def main():
    await old_style_coroutine()
```

Этот декоратор **устарел** и планируется к удалению в Python 3.10.

Этот декоратор не следует использовать для [`async def`](https://python-all.ru/3.7/reference/compound_stmts.html#async-def) корутин.

#### `asyncio.iscoroutine(obj)`

Возвращает `True`, если *obj* является [объектом корутины](https://python-all.ru/3.7/library/asyncio-task.html#coroutine).

Этот метод отличается от [`inspect.iscoroutine()`](https://python-all.ru/3.7/library/inspect.html#inspect.iscoroutine) тем, что возвращает `True` для корутин на основе генераторов.

#### `asyncio.iscoroutinefunction(func)`

Возвращает `True`, если *func* является [корутинной функцией](https://python-all.ru/3.7/library/asyncio-task.html#coroutine).

Этот метод отличается от [`inspect.iscoroutinefunction()`](https://python-all.ru/3.7/library/inspect.html#inspect.iscoroutinefunction) тем, что возвращает `True` для корутинных функций на основе генераторов, декорированных с помощью [`@coroutine`](https://python-all.ru/3.7/library/asyncio-task.html#asyncio.coroutine).
