Терминология#

  • цикл событий (event loop) - менеджер управляющий различными задачами и сопрограммами

  • сопрограмма (coroutine) в asyncio - специальный тип функций, которые создаются со словом async перед определением.

  • future - это объект, который представляет отложенное вычисление.

  • задача (task) - отвечает за управление работой сопрограммы, запрашивает статус сопрограммы. Является подклассом Future.

Блокирующий/неблокирующий вызов#

Примечание

Технически любой вызов функции блокирующий, но тут обсуждается терминология относящаяся к операциям ввода-вывода.

Блокирующий вызов останавливает работу программы, пока не будет получен результат вызова. Например, subprocess.run это блокирующий вызов и если вызвать, к примеру, ping какого-то адреса, то строка с subprocess.run будет блокировать выполнение скрипта пока не отработает ping.

Неблокирующий вызов возвращает какой-то объект сразу и, как правило, предполагается что позже надо будет еще раз вызывать какой-то метод этого объекта, чтобы получить результат вызова. Например, subprocess.Popen:

import subprocess

def ping_ip_addresses(ip_list):
    reachable = []
    unreachable = []
    result = []
    for ip in ip_list:
        p = subprocess.Popen(
            ["ping", "-c", "3", "-n", ip],
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )
        result.append(p)
    for ip, p in zip(ip_list, result):
        returncode = p.wait()
        if returncode == 0:
            reachable.append(ip)
        else:
            unreachable.append(ip)
    return reachable, unreachable

Тут вызов subprocess.Popen неблокирующий и с помощью этого вызова запущены несколько ping, но затем, чтобы получить результат, надо вызвать блокирующий p.wait.

Awaitables#

Awaitables (ожидаемые объекты) - это объекты, которые можно использовать в выражении вместе с await. Три базовых типа awaitables:

  • сопрограммы (coroutines)

  • задачи (tasks)

  • future

Coroutine (сопрограмма)#

Как и с генераторами, различают:

  • функцию сопрограмму - функция, которая создается с помощью async def

  • объект сопрограмму - объект, который возвращается при вызове функции сопрограммы

Функции-сопрограммы возвращают объекты сопрограммы, которые запускаются менеджером (циклом событий). Сопрограмма может периодически прерывать выполнение и отдавать управление менеджеру, но при этом она не теряет состояние.

Task (задача)#

Объекты класса Task используются для запуска сопрограмм в цикле событий и для отслеживания их состояния. Как только сопрограмма «обернута» в Task, например, с помощью функции asyncio.create_task, сопрограмма автоматически запущена для выполнения.

asyncio.Future#

Future - это специальный низкоуровневый объект, который представляет отложенное вычисление асинхронных операций. Чаще всего, при работе с модулем asyncio, нет необходимости создавать Future напрямую, но некоторые функции могут возвращать Future. Task является подклассом Future. Менеджер может следить за future и ожидать их завершения.

Multitasking#

  • Preemptive multitasking - ОС решает, когда надо сделать переключение

  • Cooperative multitasking - переключения указаны в коде