Производительность сетевых инструментов из стандартной библиотеки Python
Инструмент asyncio (https://docs.python.org/3/library/asyncio.html) был представлен в Python 3.4. Включает в себя идеи, почерпнутые у сообществ разработчиков вроде тех, что поддерживают библиотеки Twisted и gevent. Это инструмент для работы с конкуренцией, а самым частым приложением конкуренции являются сетевые сервера. В документации к asyncore (предшественнике asyncio) говорится следующее:
Существует лишь два способа заставить программу, работающую на одном процессоре, выполнять «больше одной задачи одновременно». Многопоточное программирование — самый простой и популярный способ сделать это, но существует еще один прием, который позволяет воспользоваться практически всеми преимуществами многопоточности, не задействуя на самом деле более одного потока. Применять этот прием имеет смысл, только если ваша программа ограничена по вводу/выводу. Если программа ограничена по процессору, то заранее запланированные потоки — это, возможно, именно то, что вам нужно. Однако сетевые сервера редко бывают ограниченными по процессору.
asyncio все еще находится в стандартной библиотеке Python на временной основе — ее API может измениться и потерять обратную совместимость, поэтому сильно не привыкайте.
Не вся функциональность нова — asyncore (объявлена устаревшей в Python 3.4) имеет цикл событий, асинхронные сокеты[105] и асинхронный ввод/вывод информации из файлов, а asynchat (также объявлена устаревшей в Python 3.4) имеет асинхронные очереди[106]. В asyncio добавлен один важный элемент — формализованная реализация сопрограмм. В Python это формально определяется как функция сопрограммы, то есть функция, чье описание начинается с конструкции async def, а не просто с def (если используется старый синтаксис, то применяется декоратор @asyncio.coroutine), и как объект, получаемый путем вызова функции сопрограммы (некого рода вычислений или операций ввода/вывода). Сопрограмма может обращаться к процессору и получить возможность участвовать в асинхронном цикле событий по очереди вместе с другими сопрограммами.
105
Сокет состоит из трех элементов: IP-адреса, включая номер порта, транспортного протокола (вроде TCP/UDP) и канала ввода/вывода (объект, похожий на файл). В документации к Python приводится отличное введение в тему сокетов (https://docs.python.org/3/howto/sockets.html).
106
Для очереди не требуются IP-адрес или протокол, поскольку она реализуется на одном компьютере; вы просто записываете в нее данные — и другой процесс может их прочитать. Очередь похожа на multiprocessing.Queue, но здесь операции ввода/вывода выполняются асинхронно.