Терминология#
цикл событий (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 - переключения указаны в коде