Модуль Asyncio Python - Блог ITVDN
ITVDN: курси програмування
Відеокурси з
програмування
УКР
  • РУС
  • УКР

    Вибери свою IT спеціальність

    Підписка
    УКР
    • РУС
    • УКР
    Arrow
    🌷Набір груп на навчання з ментором - FrontEnd, .NET, Python, Java, FullStack, QA.
    Arrow

    Модуль Asyncio Python

    advertisement advertisement

    Введение

    Мы продолжаем цикл статей об асинхронном программировании с использованием сопрограмм в Python. В предыдущей статье мы рассмотрели реализацию сопрограмм при помощи генераторов в Python 2.5 и выше, в этой же познакомимся с той инфраструктурой, которая построена на основе них в Python 3.


    В Python 3.4 был включён модуль asyncio, который, на самом деле, был доступен в виде отдельного пакета на PyPI ещё для Python 3.3. Этот модуль предоставляет всю необходимую инфраструктуру для написания однопоточного конкурентного кода с использованием сопрограмм неблокирующего ввода-вывода, мультиплексирования ввода-вывода через сокеты и другие ресурсы, запуска сетевых клиентов и серверов и т.д.

    Его возможности:

    • цикл событий с разными его реализациями, оптимизированными для различных операционных систем;
    • абстракции «транспорта» и «протокола» (подобные тем, что используются в фреймворке Twisted);
    • поддержка TCP, UDP, SSL, конвейеров UNIX-процессов, отложенных вызовов;
    • адаптированный для использования с циклом событий класс Future, который представляет ещё не вычисленный результат асинхронной функции;
    • сопрограммы и задачи, основанные на основе генераторов;
    • поддержка отмены Future и сопрограмм;
    • примитивы синхронизации для использования с сопрограммами;
    • возможность запуска задач в пуле потоков либо пуле процессов, что позволяет даже взаимодействовать с библиотеками, которые совершают блокирующий ввод-вывод.

    В основе модуля asyncio лежит цикл событий (event loop). Он отвечает за:

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

    Сопрограммы в asyncio – это генераторы, которые отвечают определённым требованиям. Ко всем сопрограммам должен быть применён декоратор @asyncio.coroutine.

    Действия, которые поддерживают сопрограммы asyncio:

    • result = yield from future – приостановка выполнения сопрограммы до получения future значения и присвоение этого значения переменной result (если future отменён, возникает исключение CancelledError);
    • result = yield from coroutine – ожидание завершения работы другой сопрограммы и получение её результата;
    • return result – возврат значения в сопрограмму, ожидающую данную;
    • raise exception – выброс исключения для обработки его ожидающей сопрограммой (если оно не обработано в текущей).

    Рассмотрим пример двух сопрограмм, одна из которых вызывает другую, производящую какие-то затратные вычисления (на самом деле, для простоты примера она будет просто приостанавливать своё выполнение на одну секунду и возвращать квадрат числа).

    import asyncio

    @asyncio.coroutine

    def time_consuming_computation(x):

        print('Computing {0} ** 2...'.format(x))

        yield from asyncio.sleep(1)

        return x ** 2

    @asyncio.coroutine

    def process_data(x):

        result = yield from time_consuming_computation(x)

        print('{0} ** 2 = {1}'.format(x, result))

    if __name__ == '__main__':

        loop = asyncio.get_event_loop()

        loop.run_until_complete(process_data(238))

        loop.close()

    Функция get_event_loop модуля asyncio возвращает объект цикла событий, и мы используем его метод run_until_complete для запуска сопрограммы.

    Какое же в данном случае преимущество перед обыкновенными функциями? Во время работы сопрограммы asyncio.sleep выполнение программы не блокируется, и, если бы у нас были другие запланированные для выполнения задачи, они могли бы в это время выполняться в том же самом потоке.

    Данные сопрограмм

    Несмотря на то, что данные сопрограммы выглядят как обычный последовательный код, на самом деле отдельные их части исполняются асинхронно. На схеме выше показано, в каком порядке исполняется код из примера.

    Можем переписать созданный ранее пример при помощи модуля asyncio.

    import asyncio

    import random

    import time

    @asyncio.coroutine

    def consume():

        """Сопрограмма обработки данных"""

        running_sum = 0

        count = 0

        while True:

            data = yield from produce()

            running_sum += data

            count += 1

            print('Got data: {}\nTotal count: {}\nAverage: {}\n'.format(

                data, count, running_sum / count))

    @asyncio.coroutine

    def produce():

        """Сопрограмма выдачи данных."""

        yield from asyncio.sleep(0.5)

        data = random.randint(0, 100)

        return data

    def main():

        loop = asyncio.get_event_loop()

        loop.run_until_complete(consume())

        loop.close()

    if __name__ == '__main__':

        main()

     

    Обратите внимание, что пришлось изменить логику его работы: теперь основной является сопрограмма consumer, а producer выдаёт одну порцию данных. Причиной этого является рассмотренные ранее ограничения, накладываемые на сопрограммы asyncio, которые логично следуют из основного предназначения данного модуля: совершение асинхронного ввода-вывода. В более реальном примере аналог сопрограммы producer мог бы, например, получать данные с внешнего сервера или базы данных.

    КОМЕНТАРІ ТА ОБГОВОРЕННЯ
    advertisement advertisement

    Купуй передплатуз доступом до всіх курсів та сервісів

    Бібліотека сучасних IT знань у зручному форматі

    Вибирай свій варіант підписки залежно від завдань, що стоять перед тобою. Але якщо потрібно пройти повне навчання з нуля до рівня фахівця, краще вибирати Базовий або Преміум. А для того, щоб вивчити 2-3 нові технології, або повторити знання, готуючись до співбесіди, підійде Пакет Стартовий.

    Стартовий
    • Усі відеокурси на 3 місяці
    • Тестування з 10 курсів
    • Перевірка 5 домашніх завдань
    • Консультація з тренером 30 хв
    59.99 $
    Придбати
    Базовий
    • Усі відеокурси на 6 місяців
    • Тестування з 16 курсів
    • Перевірка 10 домашніх завдань
    • Консультація з тренером 60 хв
    89.99 $
    Придбати
    Преміум
    • Усі відеокурси на 12 місяців
    • Тестування з 24 курсів
    • Перевірка 20 домашніх завдань
    • Консультація з тренером 120 хв
    169.99 $
    Придбати
    Notification success