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

Элементы цикла событий
Цикл событий включает в себя следующие элементы:
1. Селектор (Selector) — слушает события от операционной системы и передаёт работу корутинам, которые ждут обработки IO-сообщений.
2. Корутина для выполнения работы с IO (IO tasks) — в планировщик добавляется специальная задача для обработки IO-событий от операционной системы.
3. Планировщик (Scheduler) — обрабатывает задачи в очереди задач и следит за их правильным переключением между собой. Ключевой элемент всей программы.
4. Системный вызов (System Call) — блоки кода, которые расширяют функциональность планировщика.
5. Очередь задач (Task Queue) — в очереди собираются новые задачи на исполнение.
6. Задача (Task) — основной блок работы цикла программы. В задачах хранится информация о выполняемой корутине. Умеет обрабатывать цепочку вложенных корутин.
7. Корутина (Coroutine) — исполняемый код, которым оперирует планировщик задач.
Простейшая программа
Рассмотрим простейшую программу на Python с использованием asyncio.
import asyncio
async def calc(n: int):
result = n ** 2
await asyncio.sleep(2)
return result
async def run(n: int):
result = await calc(n)
print(result)
if __name__ == '__main__':
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
asyncio.run(run(2))
loop.close()Изменения в Python 3.11
Сразу отметим, что в более ранних версиях Python можно было просто получить текущий цикл событий через функцию asyncio.get_event_loop(), а затем передать в него корутину через loop.run_until_complete(func_coro()). Но начиная с версии Python 3.11 такой код будет вызывать ошибку.